无尘阁日记

无尘阁日记

跟AI沟通完成一个跟三方OA的对接工作之三
2026-03-11

我问:

CREATE TABLE `bridge_filing_record`

(

`id`            BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,

`tenant_id`     BIGINT UNSIGNED NOT NULL,

`partner_id`    BIGINT UNSIGNED NOT NULL,

`oa_project_id` BIGINT UNSIGNED          DEFAULT NULL,

`submission_id` BIGINT UNSIGNED          DEFAULT NULL,

`filing_no`     VARCHAR(64)              DEFAULT NULL,

`filing_status` VARCHAR(32)     NOT NULL DEFAULT 'PENDING',

`source_type`   VARCHAR(32)     NOT NULL COMMENT 'OA_PUSH/ZPY_PULL/ZPY_CREATE',

`request_body`  JSON                     DEFAULT NULL,

`response_body` JSON                     DEFAULT NULL,

`created_at`    DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,

`updated_at`    DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

PRIMARY KEY (`id`),

KEY `idx_submission_id` (`submission_id`),

KEY `idx_filing_status` (`filing_status`)

) ENGINE = InnoDB COMMENT ='报备主表';


CREATE TABLE `bridge_filing_detail`

(

`id`                   BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,

`filing_record_id`     BIGINT UNSIGNED NOT NULL,

`contract_no`          VARCHAR(128)             DEFAULT NULL,

`contract_name`        VARCHAR(255)             DEFAULT NULL,

`report_no`            VARCHAR(128)             DEFAULT NULL,

`sign_appraiser_names` VARCHAR(500)             DEFAULT NULL,

`detail_json`          JSON                     DEFAULT NULL,

`created_at`           DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`id`),

KEY `idx_filing_record_id` (`filing_record_id`)

) ENGINE = InnoDB COMMENT ='报备详情表';



这两张报备表还得增强一下。

一个是OA提交我这里报备,和我拉取她的某立项信息完成报备,还有我们系统不依赖他们自备信息完成报备,还有不依赖我们系统报告底稿完成报备,需要明确区分。

另外呢报备细节表需要对方推送评协的账号、密码,当然也可以用我们系统的账号密码,但是我们现在系统是需要用户手动输入的,当然如果能拿到企业对应的账号密码也可以自动登录,那就需要从OA获取到,或者他们推送过来。另外他们推送报备或者我们拉取他们的报备所需立项信息、合同、报告等,也需要记录日志,并且各种状态也需要记录下来,备后面查错,因此里面应该也有request_id,另外我们还得加一个提交评协的记录日志,方便记录跟评协沟通的情况。请你基于我的反馈再做增强设计。

AI答:

你这次提的几个点都很关键,实际上已经不是“补两个字段”那么简单了,而是要把“报备这件事”的来源、依赖关系、调用链路、账号来源、评协提交过程,全部做成一套可追踪、可审计、可排错的模型。

我先把核心问题给你捋顺,再给你一套增强后的表设计 SQL。

一、你现在这两张表,缺的不是字段,而是“业务维度”

你现在的 bridge_filing_recordbridge_filing_detail,只能大概记录“有一笔报备”和“下面有若干详情”。

但你实际业务里,至少有下面几类情况要区分:

1. 报备发起来源不同

不是只有一种“报备”。

你现在至少有这几种:

1)OA主动推送给你后,你来报备

这是“对方触发,我方执行”。

2)你主动去拉取对方立项信息,然后完成报备

这是“我方触发,从对方取数后执行”。

3)完全不依赖对方系统的立项信息,由我们系统自己报备

这是“我方自有数据直报”。

4)不依赖我们系统报告底稿完成报备

这说明报备材料来源,不一定来自你们系统底稿,也可能是人工补录、对方推送、第三方文件,或者只报基础立项信息。

所以这里不能只用一个 source_type 去混着表达,至少要拆成两个维度:

一个叫“谁发起的”,一个叫“数据依赖什么”。

否则后面一查错,你只看到 OA_PUSH,但根本不知道它到底是:
是 OA 推了立项+合同+报告,
还是 OA 只推了个 projectId,然后你再去拉,
还是根本没用 OA,只是你们自己填的。

这三种处理链路完全不一样。

2. 报备账号来源不同

你说得很对,评协账号密码也有几种来源:

1)对方 OA 推送过来

2)你主动从 OA 拉取企业对应账号

3)使用我们系统保存的企业账号

4)用户手工输入

5)本次临时输入但不落库

如果不把“账号来源”和“账号快照”分开记录,后面就会很难排查:

这次报备到底是用了哪套账号?
为什么自动登录失败?
到底是 OA 推错了,还是本地账号过期了,还是用户当时输错了?

所以需要:
一个企业级账号配置表,
再加一个“本次报备使用了什么账号来源、使用了哪个账号快照”的字段。

3. 缺请求流水和链路日志

你提到 request_id,这个非常对。

因为报备这种事情,天然是多步链路:

拿立项信息
拿合同
拿报告
组织报备报文
提交评协
查询评协结果
回写状态

如果没有统一的 request_id / trace_id,后面查问题会非常痛苦。

最好这样设计:

request_id

表示一次外部交互请求的唯一流水。
比如“本次向 OA 拉合同”。

trace_id

表示整笔报备全链路唯一标识。
一笔报备下的所有请求、日志、状态变更,都挂在同一个 trace_id 下。

这样你以后查日志时,一眼能把整条链串起来。

4. 缺状态流转日志

主表只存当前状态不够,必须有状态变更表。

否则你只能看到最后是 FAILED,但不知道它经历了什么:

是拉立项失败?
还是合同缺失?
还是评协登录失败?
还是提交成功后查询失败?
还是评协返回业务校验失败?

所以主表存“当前态”,日志表存“过程态”。

5. 缺“评协交互日志”

你提到“提交评协的记录日志,方便记录跟评协沟通的情况”,这个要单独建表,不能塞在主表。

因为它不是只有一次提交,可能会有:

首次提交
重新提交
补充材料
查询结果
人工备注
客服沟通记录
异常截图/响应文本

这些都是一对多关系。

二、建议的整体模型

建议你把报备相关拆成下面几层:

1. 报备主表

一笔报备任务一条。

2. 报备明细表

一笔报备下面可能有多个合同/报告明细。

3. 报备请求流水表

记录 OA 推送、我方拉取、评协提交、评协查询等每一次请求。

4. 报备状态日志表

记录每次状态变化。

5. 评协账号表

企业维度的账号配置。

6. 报备使用账号快照/来源字段

记录本次到底用的是哪套账号。

7. 评协交互日志表

记录提交、查询、补录、人工备注等。

三、关键字段设计建议

1. 主表里要新增的核心维度

filing_initiator

谁发起的
可取值:
OA_PUSH 对方推送触发
ZPY_PULL 我方主动拉取触发
ZPY_MANUAL 我方人工发起
SYSTEM_AUTO 系统自动任务触发

filing_mode

报备模式
可取值建议:
OA_FULL_DATA 依赖 OA 完整数据报备
OA_PROJECT_PULL 通过 OA 立项信息拉取后报备
ZPY_SELF_DATA 仅依赖我方系统数据报备
MANUAL_FILL 人工补录数据报备
NO_DRAFT_REQUIRED 不依赖我方报告底稿报备

这个字段比你原来的 source_type 更清晰,因为它不是在说“谁调了谁”,而是在说“这笔报备的数据依赖方式是什么”。

data_source_summary

可选,简短说明本次数据来源组合,比如:
OA_PROJECT+OA_CONTRACT+LOCAL_ACCOUNT
LOCAL_PROJECT+MANUAL_REPORT+OA_ACCOUNT

这个字段虽然不是强约束,但排查时特别有用。

2. 账号相关字段

主表增加:

account_source

本次评协账号来源
OA_PUSH
OA_PULL
LOCAL_CONFIG
USER_INPUT
TEMP_INPUT

account_config_id

如果使用系统保存账号,则指向账号配置表

account_snapshot_json

本次使用的账号快照,建议只保存脱敏后的用户名、企业名、来源、抓取时间等,不建议明文存密码

如果业务必须保存密码,也建议至少做加密存储,不要明文直接进普通字段。

3. 链路追踪字段

主表增加:

trace_id

整笔报备链路号

latest_request_id

最后一次请求流水号,方便定位最新动作

请求表增加:

request_id

本次请求唯一号

parent_request_id

如果本次请求是由前一步触发的,可以串链

trace_id

归属哪一笔报备链路

四、我给你的增强版 SQL

下面这版我尽量保持你原本的命名风格,同时把你提到的业务都补进去。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- =========================
-- 1. 报备主表
-- =========================
DROP TABLE IF EXISTS `bridge_filing_record`;
CREATE TABLE `bridge_filing_record`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '整笔报备链路追踪号',
    `latest_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '最新一次请求流水号',

    `oa_project_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT 'OA项目ID',
    `oa_project_code`       VARCHAR(128) DEFAULT NULL COMMENT 'OA项目编号',
    `submission_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '提审记录ID/提交记录ID',
    `local_project_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '我方本地项目ID',
    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '我方企业ID',

    `filing_no`             VARCHAR(64) DEFAULT NULL COMMENT '报备编号/备案号',
    `external_filing_no`    VARCHAR(128) DEFAULT NULL COMMENT '外部系统返回的报备号',
    
    `filing_initiator`      VARCHAR(32) NOT NULL COMMENT '报备发起方:OA_PUSH/ZPY_PULL/ZPY_MANUAL/SYSTEM_AUTO',
    `filing_mode`           VARCHAR(32) NOT NULL COMMENT '报备模式:OA_FULL_DATA/OA_PROJECT_PULL/ZPY_SELF_DATA/MANUAL_FILL/NO_DRAFT_REQUIRED',
    `data_source_summary`   VARCHAR(255) DEFAULT NULL COMMENT '数据来源摘要,如OA_PROJECT+OA_CONTRACT+LOCAL_ACCOUNT',

    `need_oa_project`       TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA立项信息:0否1是',
    `need_oa_contract`      TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA合同信息:0否1是',
    `need_oa_report`        TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA报告信息:0否1是',
    `need_local_draft`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否依赖我方报告底稿:0否1是',

    `account_source`        VARCHAR(32) DEFAULT NULL COMMENT '评协账号来源:OA_PUSH/OA_PULL/LOCAL_CONFIG/USER_INPUT/TEMP_INPUT',
    `account_config_id`     BIGINT UNSIGNED DEFAULT NULL COMMENT '使用的本地账号配置ID',
    `account_snapshot_json` JSON DEFAULT NULL COMMENT '本次使用的账号快照(建议脱敏)',

    `filing_status`         VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '当前状态:PENDING/WAITING_DATA/READY/SUBMITTING/SUBMITTED/SUCCESS/FAILED/CANCELLED',
    `filing_result_code`    VARCHAR(64) DEFAULT NULL COMMENT '最终结果码',
    `filing_result_msg`     VARCHAR(1000) DEFAULT NULL COMMENT '最终结果说明',

    `oa_data_status`        VARCHAR(32) DEFAULT NULL COMMENT 'OA资料状态:NOT_REQUIRED/PENDING/PARTIAL/READY/FAILED',
    `association_status`    VARCHAR(32) DEFAULT NULL COMMENT '评协提交状态:NOT_SUBMITTED/SUBMITTING/SUBMITTED/SUCCESS/FAILED',
    `sync_status`           VARCHAR(32) DEFAULT NULL COMMENT '回写/同步状态:NOT_REQUIRED/PENDING/SUCCESS/FAILED',

    `request_body`          JSON DEFAULT NULL COMMENT '创建报备时的原始请求体',
    `response_body`         JSON DEFAULT NULL COMMENT '创建报备时的原始响应体',
    `remark`                VARCHAR(1000) DEFAULT NULL COMMENT '备注',

    `created_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',
    `updated_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_trace_id` (`trace_id`),
    KEY `idx_partner_id` (`partner_id`),
    KEY `idx_submission_id` (`submission_id`),
    KEY `idx_oa_project_id` (`oa_project_id`),
    KEY `idx_local_project_id` (`local_project_id`),
    KEY `idx_filing_status` (`filing_status`),
    KEY `idx_association_status` (`association_status`),
    KEY `idx_filing_initiator` (`filing_initiator`),
    KEY `idx_filing_mode` (`filing_mode`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备主表';


-- =========================
-- 2. 报备详情表
-- 一笔报备可对应多个合同/报告明细
-- =========================
DROP TABLE IF EXISTS `bridge_filing_detail`;
CREATE TABLE `bridge_filing_detail`
(
    `id`                     BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `filing_record_id`       BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `detail_no`              INT NOT NULL DEFAULT 1 COMMENT '明细序号',
    `contract_id`            BIGINT UNSIGNED DEFAULT NULL COMMENT '合同ID',
    `contract_no`            VARCHAR(128) DEFAULT NULL COMMENT '合同编号',
    `contract_name`          VARCHAR(255) DEFAULT NULL COMMENT '合同名称',

    `report_id`              BIGINT UNSIGNED DEFAULT NULL COMMENT '报告ID',
    `report_no`              VARCHAR(128) DEFAULT NULL COMMENT '报告号',
    `report_name`            VARCHAR(255) DEFAULT NULL COMMENT '报告名称',

    `project_name`           VARCHAR(255) DEFAULT NULL COMMENT '项目名称',
    `client_name`            VARCHAR(255) DEFAULT NULL COMMENT '委托方名称',
    `sign_appraiser_names`   VARCHAR(500) DEFAULT NULL COMMENT '签字评估师姓名,多个逗号分隔',

    `data_source`            VARCHAR(32) DEFAULT NULL COMMENT '本条明细数据来源:OA_PUSH/OA_PULL/LOCAL/MANUAL',
    `detail_status`          VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '明细状态:PENDING/READY/SUBMITTED/SUCCESS/FAILED',
    `error_code`             VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`              VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `request_id`             VARCHAR(64) DEFAULT NULL COMMENT '产生/更新本明细时的请求流水号',
    `detail_json`            JSON DEFAULT NULL COMMENT '明细扩展数据',
    `created_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_contract_no` (`contract_no`),
    KEY `idx_report_no` (`report_no`),
    KEY `idx_request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备详情表';


-- =========================
-- 3. 企业评协账号配置表
-- 存企业默认账号,可由OA拉取、对方推送、用户手填等
-- =========================
DROP TABLE IF EXISTS `bridge_filing_account`;
CREATE TABLE `bridge_filing_account`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',

    `account_source`        VARCHAR(32) NOT NULL COMMENT '账号来源:OA_PUSH/OA_PULL/LOCAL_CONFIG/USER_INPUT',
    `association_org_name`  VARCHAR(255) DEFAULT NULL COMMENT '评协机构/企业名称',
    `login_username`        VARCHAR(255) NOT NULL COMMENT '登录账号',
    `login_password_enc`    VARCHAR(1000) DEFAULT NULL COMMENT '加密后的登录密码',
    `password_updated_at`   DATETIME DEFAULT NULL COMMENT '密码更新时间',

    `is_default`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认账号',
    `is_valid`              TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否有效',
    `last_verify_status`    VARCHAR(32) DEFAULT NULL COMMENT '最近校验状态:UNKNOWN/SUCCESS/FAILED',
    `last_verify_msg`       VARCHAR(1000) DEFAULT NULL COMMENT '最近校验说明',

    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '该账号来源对应请求流水号',
    `ext_json`              JSON DEFAULT NULL COMMENT '扩展数据',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_tenant_partner_enterprise` (`tenant_id`, `partner_id`, `enterprise_id`),
    KEY `idx_login_username` (`login_username`),
    KEY `idx_request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业评协账号配置表';


-- =========================
-- 4. 报备请求流水表
-- 记录OA推送、拉取、评协提交、评协查询等每一次请求
-- =========================
DROP TABLE IF EXISTS `bridge_filing_request_log`;
CREATE TABLE `bridge_filing_request_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备主表ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) NOT NULL COMMENT '请求流水号',
    `parent_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '父请求流水号',

    `request_type`          VARCHAR(32) NOT NULL COMMENT '请求类型:OA_PUSH/OA_PULL_PROJECT/OA_PULL_CONTRACT/OA_PULL_REPORT/OA_PUSH_ACCOUNT/ASSOCIATION_LOGIN/ASSOCIATION_SUBMIT/ASSOCIATION_QUERY/CALLBACK/SYNC_BACK',
    `request_direction`     VARCHAR(16) NOT NULL COMMENT '方向:INBOUND/OUTBOUND/INTERNAL',
    `request_status`        VARCHAR(32) NOT NULL DEFAULT 'PROCESSING' COMMENT '状态:PROCESSING/SUCCESS/FAILED/IGNORED',
    `biz_stage`             VARCHAR(32) DEFAULT NULL COMMENT '业务阶段:FETCH_PROJECT/FETCH_CONTRACT/FETCH_REPORT/ACCOUNT_PREPARE/SUBMIT_ASSOCIATION/QUERY_RESULT/SYNC_BACK',

    `http_method`           VARCHAR(16) DEFAULT NULL COMMENT 'HTTP方法',
    `request_url`           VARCHAR(500) DEFAULT NULL COMMENT '请求地址',
    `request_headers`       JSON DEFAULT NULL COMMENT '请求头',
    `request_body`          JSON DEFAULT NULL COMMENT '请求体',
    `response_code`         VARCHAR(64) DEFAULT NULL COMMENT '响应码',
    `response_body`         JSON DEFAULT NULL COMMENT '响应体',

    `duration_ms`           INT DEFAULT NULL COMMENT '耗时毫秒',
    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_request_id` (`request_id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_parent_request_id` (`parent_request_id`),
    KEY `idx_request_type` (`request_type`),
    KEY `idx_request_status` (`request_status`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备请求流水日志表';


-- =========================
-- 5. 报备状态流转日志表
-- 记录状态变化过程,方便排错
-- =========================
DROP TABLE IF EXISTS `bridge_filing_status_log`;
CREATE TABLE `bridge_filing_status_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '对应请求流水号',

    `status_type`           VARCHAR(32) NOT NULL COMMENT '状态类型:FILING_STATUS/OA_DATA_STATUS/ASSOCIATION_STATUS/SYNC_STATUS/DETAIL_STATUS',
    `from_status`           VARCHAR(32) DEFAULT NULL COMMENT '原状态',
    `to_status`             VARCHAR(32) NOT NULL COMMENT '新状态',

    `change_reason`         VARCHAR(255) DEFAULT NULL COMMENT '变更原因',
    `change_code`           VARCHAR(64) DEFAULT NULL COMMENT '变更码',
    `change_msg`            VARCHAR(1000) DEFAULT NULL COMMENT '变更说明',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_status_type` (`status_type`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备状态流转日志表';


-- =========================
-- 6. 评协交互日志表
-- 专门记录与评协系统交互、沟通、补充材料、人工备注等
-- =========================
DROP TABLE IF EXISTS `bridge_filing_association_log`;
CREATE TABLE `bridge_filing_association_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `action_type`           VARCHAR(32) NOT NULL COMMENT '动作类型:LOGIN/SUBMIT/RESUBMIT/QUERY/UPLOAD_ATTACHMENT/MANUAL_NOTE/CALL_ASSOCIATION/EMAIL_ASSOCIATION/OTHER',
    `action_status`         VARCHAR(32) NOT NULL DEFAULT 'SUCCESS' COMMENT '动作状态:SUCCESS/FAILED/PENDING',
    `association_account`   VARCHAR(255) DEFAULT NULL COMMENT '使用的评协账号(可脱敏)',

    `content`               VARCHAR(2000) DEFAULT NULL COMMENT '动作说明/沟通内容',
    `request_body`          JSON DEFAULT NULL COMMENT '请求体',
    `response_body`         JSON DEFAULT NULL COMMENT '响应体',
    `attachment_json`       JSON DEFAULT NULL COMMENT '附件信息',
    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_action_type` (`action_type`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评协交互日志表';

SET FOREIGN_KEY_CHECKS = 1;

五、这套设计如何对应你提的几个业务点

1. 明确区分几种报备模式

你原来一句“OA提交我这里报备,和我拉取她的某立项信息完成报备,还有我们系统不依赖他们自备信息完成报备,还有不依赖我们系统报告底稿完成报备”,本质上应该拆成两个字段:

谁发起

filing_initiator

依赖什么数据完成

filing_mode + 四个依赖开关:

need_oa_project
need_oa_contract
need_oa_report
need_local_draft

这样后面你一看就清楚。

举几个例子:

场景A:OA推完整资料给你,你直接报备

filing_initiator = OA_PUSH
filing_mode = OA_FULL_DATA
need_oa_project = 1
need_oa_contract = 1
need_oa_report = 1
need_local_draft = 0

场景B:你主动拉他们立项信息后报备

filing_initiator = ZPY_PULL
filing_mode = OA_PROJECT_PULL
need_oa_project = 1
其他看实际

场景C:完全用你们系统自己的项目和资料报备

filing_initiator = ZPY_MANUALSYSTEM_AUTO
filing_mode = ZPY_SELF_DATA
need_oa_project = 0
need_local_draft = 1

场景D:不依赖你们系统底稿

filing_mode = NO_DRAFT_REQUIRED
need_local_draft = 0

这样表达才准确。

2. 评协账号密码来源

你说“对方推送评协账号密码,也可以用我们系统的账号密码,或者用户手动输入”,这个在新设计里有两层:

企业默认账号配置

bridge_filing_account

某次报备到底用了什么

bridge_filing_record.account_source
bridge_filing_record.account_config_id
bridge_filing_record.account_snapshot_json

这样既能管理企业默认账号,又能记录某次报备用的是哪套。

六、关于密码存储,我建议你别明文

这个我专门提醒一下。

你说要记录评协账号密码,这个业务上可能确实需要,但数据库层面不要直接明文 password

建议至少这样:

1. 存加密后的密码

字段:login_password_enc

2. 主表只存快照,不存明文

account_snapshot_json 里只放:
账号名
来源
企业名
抓取时间
是否自动带出

不要直接放明文密码。

如果业务强依赖自动提交,真正提交前再解密使用。

七、为什么我没有把所有日志都塞进一个日志表

因为你这里有三类日志,本质不同:

1. 请求流水日志

关注接口调用本身
有没有请求、发给谁、入参出参、耗时、成功失败

2. 状态流转日志

关注状态变化
从什么状态变成什么状态

3. 评协交互日志

关注业务动作
登录、提交、查询、补资料、人工沟通

这三类混一起,后面会很难用。

八、你后面还可以继续增强的点

如果你准备把这块做成长期稳定模块,我建议后续再加两个增强点。

1. 补一个“报备附件表”

因为后面很可能会有:
合同附件
报告附件
评协要求补充材料
截图
回执 PDF

单纯塞 JSON 会越来越乱。

可以后续单独建:

bridge_filing_attachment

用来挂文件路径、文件类型、来源、上传状态。

2. 补一个“字典约束表”或者统一枚举

你现在状态类字段很多:

filing_status
oa_data_status
association_status
sync_status
detail_status
request_status

如果团队人多,最好统一枚举定义,不然有人写 SUCCESS,有人写 SUCCEED,有人写 DONE,后面就废了。

九、我给你的落地建议

如果你想先快速推进,不一定一次把所有表都上齐。

建议分两步:

第一阶段,先必上

bridge_filing_record
bridge_filing_detail
bridge_filing_request_log
bridge_filing_status_log

这四张已经能把主流程跑起来,并且可排错。

第二阶段,再加

bridge_filing_account
bridge_filing_association_log

这样把账号管理和评协沟通沉淀下来。

十、结论

你这次要解决的核心,不是“报备表再加几个字段”,而是把报备设计成一条完整链路:

谁发起的
依赖什么数据
用了哪套账号
中间发了哪些请求
状态如何变化
最后和评协怎么交互

我上面这套表,就是围绕这六件事展开的。

如果你愿意,我下一步可以继续直接帮你做两件事中的任意一件:

第一,把这套表再压缩成“你当前项目最适合的精简版 SQL”,避免一上来过重。

第二,继续往下帮你补完整的字段注释枚举说明文档,包括每个状态值到底怎么取。

我问:

刚刚接受到的信息,所有报备如果来自于OA,所有信息使用他们的,而如果来自我们系统,则所有系信息使用我们的,不过来自于他们的信息在我们这里可以修改,文件当让不可修改。请你依据这个信息再做增强。

AI答:

这个新增信息很重要,它把你这套报备模型里的一个核心原则彻底定下来了:

不是“字段从哪边取都行”,而是要遵循“来源主导原则”。

也就是:

一、现在业务规则已经明确了

1. 如果报备来源于 OA

那么这笔报备的业务数据,以 OA 为准。

这里的“所有信息使用他们的”,我理解为:

项目信息、合同信息、报告信息、委托方信息、评估对象信息、评估师信息、评估值、日期类字段、企业账号信息等,都默认取 OA 侧给的或从 OA 侧拉到的。

但是:

可以修改的是“结构化业务信息”

也就是你们系统里允许用户修正、补充、调整的字段。

不可修改的是“文件类资料”

也就是 OA 推过来的合同文件、报告文件、附件、扫描件等,只能引用、下载、上传、传递,不能在你们系统里直接改内容,更不能替换后还伪装成原 OA 文件。

这就意味着:
你不能只记录“当前值”,还必须记录:

原始来源值是什么
我方有没有改过
改的是哪些字段
文件是不是只读

2. 如果报备来源于你们系统

那么这笔报备的业务数据,以你们系统为准。

也就是:

项目、合同、报告、评估师、账号等都走你们自己的数据。

OA 的数据不参与主导。

这里最关键的一点是:

不是“某个字段单独来源于哪边”,而是“整笔报备先有一个主来源系统”。

然后在这个主来源系统之下,结构化字段允许在本地修订,文件类资料要按文件来源控制是否可替换。

所以,表设计上要补两个大的能力:

二、必须新增“主数据来源控制”

你原来只有:
filing_initiator
filing_mode

这还不够。

因为“谁发起”和“谁是主数据源”不是同一个概念。

比如:

OA 推送触发,这通常也是 OA 为主数据源。
但以后也可能出现你们系统发起补报备,不过数据仍以 OA 项目为基础。
所以最好单独加一个字段:

1. 主数据来源字段

建议在 bridge_filing_record 增加:

master_data_source

取值建议:

OA
ZPY

含义非常清楚:

这笔报备,整体业务数据以谁为准。

这样你后面所有取值逻辑、展示逻辑、编辑权限逻辑,都能围绕它展开。

2. 数据编辑规则字段

再加一个:

data_edit_policy

建议取值:

OA_EDITABLE_FILE_READONLY
ZPY_EDITABLE
READONLY

你当前业务主要会用到前两种:

OA 来源

OA_EDITABLE_FILE_READONLY
意思是:
结构化字段可在我方修改;
文件不可修改。

我方来源

ZPY_EDITABLE
意思是:
结构化字段按我方数据走;
我方文件可按我方规则维护。

三、必须新增“原始值 + 当前值 + 是否改动”能力

因为你刚刚说了一个很关键的话:

“来自于他们的信息在我们这里可以修改,文件当然不可修改。”

这句话的本质不是“允许编辑”这么简单,而是:

系统要能区分:
这是 OA 原值
这是我方修改后的当前值
这个字段被改过没有

否则将来你根本没法解释:

为什么最终报备的数据跟 OA 原始数据不一致?
是谁改的?
改了什么?
文件为什么不能改,但名称怎么变了?

所以,建议把“报备详情表”增强成同时支持原始值和当前值,或者单独做一个字段覆盖表。

从工程落地来说,我建议不要在主表里给每个字段都做两套列,那会爆炸。最合理的做法是:

四、增加“字段覆盖表”

专门记录:哪些来源字段被本地改了。

这样设计最灵活。

新增一张表:

bridge_filing_field_override

用途是:
记录某笔报备、某个明细、某个字段,原始值是什么,当前覆盖值是什么,是否来自 OA,是否允许覆盖,谁改的。

这样你主表和详情表仍然保留“最终当前值”,同时这张表保留差异审计。

五、文件必须单独建表,并增加只读控制

你刚才补充“文件当然不可修改”,这个其实不能只靠业务口头约定,必须落表控制。

因为文件是最容易出争议的地方。

建议新增:

bridge_filing_file

字段要明确:

文件来源:OA / ZPY / MANUAL
是否只读:is_readonly
是否允许替换:is_replaceable
原始文件名、存储路径、文件类型、上传时间、请求流水号

对于 OA 来源文件:

file_source = OA
is_readonly = 1
is_replaceable = 0

这样前后端、接口层、服务层都能统一判断。

六、请求日志也要能区分“取数”和“改数”

以前你有请求日志,但现在你需要把下面几种行为分开:

1. OA 推送原始数据

2. 我方从 OA 拉原始数据

3. 用户在我方系统修改结构化字段

4. 文件引用/下载/上传

5. 提交评协时实际使用的数据快照

也就是说,光记录“请求成功失败”不够了,还要记录“最终提交给评协的快照”。

所以建议再加一个:

submit_snapshot_json

放在 bridge_filing_record 或单独放一张提交快照表里。

它的意义是:

不管中间改过多少次,真正提交评协那一刻,最终用了哪些字段值、哪些账号、哪些文件引用,一定要有快照。

否则后面出了问题,你没法复盘。

七、基于你这次补充后,推荐的增强点

下面我直接给你明确该怎么改。

一)修改报备主表 bridge_filing_record

新增这些字段最关键:

ALTER TABLE `bridge_filing_record`
ADD COLUMN `master_data_source` VARCHAR(16) NOT NULL DEFAULT 'ZPY' COMMENT '主数据来源:OA/ZPY' AFTER `filing_mode`,
ADD COLUMN `data_edit_policy` VARCHAR(64) NOT NULL DEFAULT 'ZPY_EDITABLE' COMMENT '数据编辑策略:OA_EDITABLE_FILE_READONLY/ZPY_EDITABLE/READONLY' AFTER `master_data_source`,
ADD COLUMN `source_snapshot_json` JSON DEFAULT NULL COMMENT '来源系统原始数据快照' AFTER `account_snapshot_json`,
ADD COLUMN `submit_snapshot_json` JSON DEFAULT NULL COMMENT '最终提交评协时的数据快照' AFTER `source_snapshot_json`,
ADD COLUMN `has_field_override` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在字段覆盖修改:0否1是' AFTER `submit_snapshot_json`,
ADD COLUMN `has_readonly_file` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在只读文件:0否1是' AFTER `has_field_override`;

这几个字段分别解决:

master_data_source

整笔报备数据到底以 OA 还是 ZPY 为准。

data_edit_policy

控制编辑规则,不再靠口头约定。

source_snapshot_json

保存来源系统原始快照。
如果来自 OA,就保存 OA 原始项目/合同/报告结构。
如果来自你们系统,就保存你们自己的原始结构。

submit_snapshot_json

真正提交评协时用的最终快照。

has_field_override

这笔报备有没有对来源字段做过本地修改。

has_readonly_file

这笔报备有没有只读文件。

八、二)修改报备详情表 bridge_filing_detail

详情表建议增加字段来源和是否可编辑控制:

ALTER TABLE `bridge_filing_detail`
ADD COLUMN `master_data_source` VARCHAR(16) NOT NULL DEFAULT 'ZPY' COMMENT '本明细主数据来源:OA/ZPY' AFTER `data_source`,
ADD COLUMN `is_editable` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '结构化字段是否允许编辑:0否1是' AFTER `master_data_source`,
ADD COLUMN `has_override` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '本明细是否有字段被覆盖修改:0否1是' AFTER `is_editable`,
ADD COLUMN `source_detail_json` JSON DEFAULT NULL COMMENT '来源系统原始明细快照' AFTER `detail_json`,
ADD COLUMN `final_detail_json` JSON DEFAULT NULL COMMENT '本明细最终使用快照' AFTER `source_detail_json`;

这里的意思是:

source_detail_json

原始明细长什么样。

final_detail_json

最后实际拿去报备的明细长什么样。

这个非常关键,因为将来一个合同号、报告号、评估师名单变了,你可以明确对比原始值和最终值。

九、三)新增字段覆盖表

这是这次增强里最关键的一张表之一。

DROP TABLE IF EXISTS `bridge_filing_field_override`;
CREATE TABLE `bridge_filing_field_override`
(
    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID,可为空,表示主表级字段',

    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `master_data_source`  VARCHAR(16) NOT NULL COMMENT '主数据来源:OA/ZPY',
    `field_scope`         VARCHAR(32) NOT NULL COMMENT '字段范围:RECORD/DETAIL/ACCOUNT',
    `field_name`          VARCHAR(128) NOT NULL COMMENT '字段名',
    `field_label`         VARCHAR(255) DEFAULT NULL COMMENT '字段中文名',

    `source_value`        TEXT COMMENT '来源原始值',
    `current_value`       TEXT COMMENT '当前值/覆盖后的值',
    `is_overridden`       TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否被覆盖:0否1是',
    `override_reason`     VARCHAR(255) DEFAULT NULL COMMENT '修改原因',
    `override_type`       VARCHAR(32) DEFAULT NULL COMMENT '修改类型:MANUAL_FIX/SYSTEM_FIX/DATA_CLEAN/FIELD_MAPPING',

    `operator_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`       VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_field_name` (`field_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备字段覆盖修改表';

这张表能解决什么?

比如 OA 推来的:
委托方名称 = “湖北某某公司”

后来你们这边人工改成:
“湖北某某有限公司”

那就记一条:

原值是什么
改后值是什么
谁改的
为什么改

以后查错非常清楚。

十、四)新增报备文件表

你这次强调“文件不可修改”,所以一定得做文件表,不然没法真正控制。

DROP TABLE IF EXISTS `bridge_filing_file`;
CREATE TABLE `bridge_filing_file`
(
    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',

    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `file_source`         VARCHAR(16) NOT NULL COMMENT '文件来源:OA/ZPY/MANUAL',
    `file_category`       VARCHAR(32) NOT NULL COMMENT '文件类别:CONTRACT/REPORT/ATTACHMENT/OTHER',
    `file_name`           VARCHAR(255) NOT NULL COMMENT '文件名',
    `file_ext`            VARCHAR(32) DEFAULT NULL COMMENT '扩展名',
    `file_size`           BIGINT UNSIGNED DEFAULT NULL COMMENT '文件大小,单位字节',
    `file_path`           VARCHAR(1000) DEFAULT NULL COMMENT '存储路径',
    `file_url`            VARCHAR(1000) DEFAULT NULL COMMENT '访问地址',
    `file_hash`           VARCHAR(128) DEFAULT NULL COMMENT '文件哈希',
    `mime_type`           VARCHAR(128) DEFAULT NULL COMMENT '文件MIME类型',

    `is_readonly`         TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否只读:0否1是',
    `is_replaceable`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许替换:0否1是',
    `file_status`         VARCHAR(32) NOT NULL DEFAULT 'ACTIVE' COMMENT '文件状态:ACTIVE/DELETED/INVALID',

    `source_file_id`      VARCHAR(128) DEFAULT NULL COMMENT '来源系统文件ID',
    `remark`              VARCHAR(1000) DEFAULT NULL COMMENT '备注',
    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_file_source` (`file_source`),
    KEY `idx_file_category` (`file_category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备文件表';

十一、文件规则怎么落地最合适

根据你现在的新规则,我建议把文件规则定成下面这样:

1. OA 来源报备

结构化字段:可改
OA 文件:只读,不可替换

所以创建 OA 文件记录时:

file_source = 'OA'
is_readonly = 1
is_replaceable = 0

2. ZPY 来源报备

结构化字段:按我方规则可维护
我方文件:通常可替换

所以创建 ZPY 文件记录时:

file_source = 'ZPY'
is_readonly = 0
is_replaceable = 1

十二、五)请求日志也建议补一个“数据快照类型”

因为你现在已经不是简单的接口日志了,而是“这个请求拿到的是来源原始数据,还是提交评协最终数据”。

建议在 bridge_filing_request_log 增加:

ALTER TABLE `bridge_filing_request_log`
ADD COLUMN `data_snapshot_type` VARCHAR(32) DEFAULT NULL COMMENT '数据快照类型:SOURCE/FINAL/FILE_ONLY/PARTIAL' AFTER `biz_stage`;

这样:
拉 OA 项目时,可以记 SOURCE
提交评协时,可以记 FINAL
只传文件时,可以记 FILE_ONLY

十三、六)状态日志里也建议补“是否来源修改触发”

因为现在很多状态变化,不只是接口调用导致,也可能是人工修改字段后进入“待重新提交”。

建议:

ALTER TABLE `bridge_filing_status_log`
ADD COLUMN `trigger_type` VARCHAR(32) DEFAULT NULL COMMENT '触发方式:REQUEST_RESPONSE/MANUAL_EDIT/SYSTEM_RETRY/AUTO_SYNC' AFTER `to_status`;

十四、现在这套设计的业务逻辑就完整了

你这次补充后,整个逻辑其实可以抽象成一句话:

1. 报备先确定主来源系统

来自 OA,就以 OA 为主
来自 ZPY,就以 ZPY 为主

2. 结构化字段允许在我方系统修订

但必须保留原始值、修改痕迹、最终值

3. 文件按来源控制权限

OA 文件只读不可改
ZPY 文件按本地规则处理

4. 提交评协时必须固化最终快照

这样以后任何问题都能复盘

十五、我给你一个更明确的落地建议

如果你不想一下子建太多表,我建议你最少先补下面三件:

必补一:主表加来源控制和快照

也就是:
master_data_source
data_edit_policy
source_snapshot_json
submit_snapshot_json

必补二:建字段覆盖表

bridge_filing_field_override

因为只要允许修改来源数据,这张表几乎是必需的。

必补三:建文件表

bridge_filing_file

因为你已经明确文件不可修改,这个规则必须实体化。

十六、最后我帮你把这次新增规则翻译成一句数据库设计原则

你现在这块最核心的设计原则可以写成:

“报备按主来源系统驱动取数。来源于 OA 的业务数据默认以 OA 为准,来源于我方系统的业务数据默认以我方为准。结构化字段允许在我方系统进行覆盖修订,并保留原始值与修改痕迹;文件类资料按来源系统进行只读控制,OA 来源文件不可修改、不可替换。”

这句话其实已经可以写到你们设计文档里了。

下一步我可以直接继续帮你做一版“整合后的最终 SQL”,把前一版和这次补充的增强全部揉成一套完整建表语句。

我问:

生成吧。

AI答:

下面我直接给你一套整合后的最终增强版 SQL。

这一版已经把你前面几次反馈都融合进去了,重点解决这些问题:

第一,区分报备到底来自 OA 还是来自我们系统。
第二,明确“整笔报备以谁的数据为准”。
第三,来自 OA 的结构化信息允许在我方修改,但文件只读不可改。
第四,账号密码可以来自 OA 推送、OA 拉取、本地配置、用户输入。
第五,要有完整的请求流水、状态流转、评协交互记录。
第六,要能记录字段覆盖修改痕迹。
第七,要能记录最终提交评协时到底用了什么数据快照。

我尽量保持你的命名风格是 bridge_ 前缀,字段名也尽量直白,方便你后面直接落地。

一、设计原则先定死

你后面代码逻辑、接口逻辑、前端编辑逻辑,都可以按下面这个原则走:

1. 主来源系统原则

如果报备来自 OA,则整笔报备的主数据来源是 OA。
如果报备来自我们系统,则整笔报备的主数据来源是 ZPY。

对应字段:
master_data_source

取值:
OA
ZPY

2. 编辑原则

如果主来源是 OA:
结构化字段可修改;
OA 文件不可修改、不可替换。

如果主来源是 ZPY:
结构化字段按我方规则维护;
我方文件可按我方规则维护。

对应字段:
data_edit_policy

推荐取值:
OA_EDITABLE_FILE_READONLY
ZPY_EDITABLE
READONLY

3. 快照原则

必须同时保存:

来源系统原始快照
最终提交评协快照

否则以后无法复盘。

二、整合后的最终 SQL

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- =========================================================
-- 1. 报备主表
-- 一笔报备任务一条记录
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_record`;
CREATE TABLE `bridge_filing_record`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '整笔报备链路追踪号',
    `latest_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '最新一次请求流水号',

    `oa_project_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT 'OA项目ID',
    `oa_project_code`       VARCHAR(128) DEFAULT NULL COMMENT 'OA项目编号',
    `local_project_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '我方系统项目ID',
    `submission_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '提交记录ID/提审记录ID',

    `filing_no`             VARCHAR(64) DEFAULT NULL COMMENT '我方报备编号',
    `external_filing_no`    VARCHAR(128) DEFAULT NULL COMMENT '外部系统返回的报备号/备案号',

    `filing_initiator`      VARCHAR(32) NOT NULL COMMENT '报备发起方:OA_PUSH/ZPY_PULL/ZPY_MANUAL/SYSTEM_AUTO',
    `filing_mode`           VARCHAR(32) NOT NULL COMMENT '报备模式:OA_FULL_DATA/OA_PROJECT_PULL/ZPY_SELF_DATA/MANUAL_FILL/NO_DRAFT_REQUIRED',

    `master_data_source`    VARCHAR(16) NOT NULL COMMENT '主数据来源:OA/ZPY',
    `data_edit_policy`      VARCHAR(64) NOT NULL COMMENT '编辑策略:OA_EDITABLE_FILE_READONLY/ZPY_EDITABLE/READONLY',
    `data_source_summary`   VARCHAR(255) DEFAULT NULL COMMENT '数据来源摘要,如OA_PROJECT+OA_CONTRACT+OA_REPORT+OA_ACCOUNT',

    `need_oa_project`       TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA立项信息:0否1是',
    `need_oa_contract`      TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA合同信息:0否1是',
    `need_oa_report`        TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA报告信息:0否1是',
    `need_local_draft`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否依赖我方报告底稿:0否1是',

    `account_source`        VARCHAR(32) DEFAULT NULL COMMENT '评协账号来源:OA_PUSH/OA_PULL/LOCAL_CONFIG/USER_INPUT/TEMP_INPUT',
    `account_config_id`     BIGINT UNSIGNED DEFAULT NULL COMMENT '使用的本地账号配置ID',
    `account_snapshot_json` JSON DEFAULT NULL COMMENT '本次使用账号快照,建议脱敏存储',

    `source_snapshot_json`  JSON DEFAULT NULL COMMENT '来源系统原始数据快照',
    `submit_snapshot_json`  JSON DEFAULT NULL COMMENT '最终提交评协时的数据快照',

    `has_field_override`    TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在字段覆盖修改:0否1是',
    `has_readonly_file`     TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在只读文件:0否1是',

    `filing_status`         VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '报备状态:PENDING/WAITING_DATA/EDITING/READY/SUBMITTING/SUBMITTED/SUCCESS/FAILED/CANCELLED',
    `oa_data_status`        VARCHAR(32) DEFAULT NULL COMMENT 'OA资料状态:NOT_REQUIRED/PENDING/PARTIAL/READY/FAILED',
    `association_status`    VARCHAR(32) DEFAULT NULL COMMENT '评协状态:NOT_SUBMITTED/SUBMITTING/SUBMITTED/SUCCESS/FAILED',
    `sync_status`           VARCHAR(32) DEFAULT NULL COMMENT '同步回写状态:NOT_REQUIRED/PENDING/SUCCESS/FAILED',

    `filing_result_code`    VARCHAR(64) DEFAULT NULL COMMENT '最终结果码',
    `filing_result_msg`     VARCHAR(1000) DEFAULT NULL COMMENT '最终结果说明',

    `request_body`          JSON DEFAULT NULL COMMENT '创建报备时原始请求体',
    `response_body`         JSON DEFAULT NULL COMMENT '创建报备时原始响应体',
    `remark`                VARCHAR(1000) DEFAULT NULL COMMENT '备注',

    `created_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',
    `updated_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_trace_id` (`trace_id`),
    KEY `idx_partner_id` (`partner_id`),
    KEY `idx_enterprise_id` (`enterprise_id`),
    KEY `idx_submission_id` (`submission_id`),
    KEY `idx_oa_project_id` (`oa_project_id`),
    KEY `idx_local_project_id` (`local_project_id`),
    KEY `idx_filing_status` (`filing_status`),
    KEY `idx_association_status` (`association_status`),
    KEY `idx_filing_initiator` (`filing_initiator`),
    KEY `idx_filing_mode` (`filing_mode`),
    KEY `idx_master_data_source` (`master_data_source`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备主表';


-- =========================================================
-- 2. 报备详情表
-- 一笔报备下可有多个合同/报告/明细项
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_detail`;
CREATE TABLE `bridge_filing_detail`
(
    `id`                     BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `filing_record_id`       BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `detail_no`              INT NOT NULL DEFAULT 1 COMMENT '明细序号',

    `contract_id`            BIGINT UNSIGNED DEFAULT NULL COMMENT '合同ID',
    `contract_no`            VARCHAR(128) DEFAULT NULL COMMENT '合同编号',
    `contract_name`          VARCHAR(255) DEFAULT NULL COMMENT '合同名称',

    `report_id`              BIGINT UNSIGNED DEFAULT NULL COMMENT '报告ID',
    `report_no`              VARCHAR(128) DEFAULT NULL COMMENT '报告号',
    `report_name`            VARCHAR(255) DEFAULT NULL COMMENT '报告名称',

    `project_name`           VARCHAR(255) DEFAULT NULL COMMENT '项目名称',
    `client_name`            VARCHAR(255) DEFAULT NULL COMMENT '委托方名称',
    `sign_appraiser_names`   VARCHAR(500) DEFAULT NULL COMMENT '签字评估师姓名,多个逗号分隔',

    `data_source`            VARCHAR(32) DEFAULT NULL COMMENT '本明细数据来源:OA_PUSH/OA_PULL/LOCAL/MANUAL',
    `master_data_source`     VARCHAR(16) NOT NULL COMMENT '本明细主数据来源:OA/ZPY',
    `is_editable`            TINYINT(1) NOT NULL DEFAULT 1 COMMENT '结构化字段是否允许编辑:0否1是',
    `has_override`           TINYINT(1) NOT NULL DEFAULT 0 COMMENT '本明细是否存在字段覆盖修改:0否1是',

    `detail_status`          VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '明细状态:PENDING/EDITING/READY/SUBMITTED/SUCCESS/FAILED',
    `error_code`             VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`              VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `request_id`             VARCHAR(64) DEFAULT NULL COMMENT '产生/更新本明细时的请求流水号',
    `source_detail_json`     JSON DEFAULT NULL COMMENT '来源系统原始明细快照',
    `final_detail_json`      JSON DEFAULT NULL COMMENT '本明细最终使用快照',
    `detail_json`            JSON DEFAULT NULL COMMENT '扩展数据',

    `created_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_contract_no` (`contract_no`),
    KEY `idx_report_no` (`report_no`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_master_data_source` (`master_data_source`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备详情表';


-- =========================================================
-- 3. 企业评协账号配置表
-- 可来自OA推送、OA拉取、本地维护、用户录入
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_account`;
CREATE TABLE `bridge_filing_account`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',

    `account_source`        VARCHAR(32) NOT NULL COMMENT '账号来源:OA_PUSH/OA_PULL/LOCAL_CONFIG/USER_INPUT',
    `association_org_name`  VARCHAR(255) DEFAULT NULL COMMENT '评协机构/企业名称',
    `login_username`        VARCHAR(255) NOT NULL COMMENT '登录账号',
    `login_password_enc`    VARCHAR(1000) DEFAULT NULL COMMENT '加密后的登录密码',
    `password_updated_at`   DATETIME DEFAULT NULL COMMENT '密码更新时间',

    `is_default`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认账号',
    `is_valid`              TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否有效',
    `last_verify_status`    VARCHAR(32) DEFAULT NULL COMMENT '最近校验状态:UNKNOWN/SUCCESS/FAILED',
    `last_verify_msg`       VARCHAR(1000) DEFAULT NULL COMMENT '最近校验说明',

    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '来源对应请求流水号',
    `ext_json`              JSON DEFAULT NULL COMMENT '扩展数据',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_tenant_partner_enterprise` (`tenant_id`, `partner_id`, `enterprise_id`),
    KEY `idx_login_username` (`login_username`),
    KEY `idx_request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业评协账号配置表';


-- =========================================================
-- 4. 报备字段覆盖修改表
-- 记录来源数据被本地覆盖修改的痕迹
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_field_override`;
CREATE TABLE `bridge_filing_field_override`
(
    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID,可为空,表示主表级字段',

    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `master_data_source`  VARCHAR(16) NOT NULL COMMENT '主数据来源:OA/ZPY',
    `field_scope`         VARCHAR(32) NOT NULL COMMENT '字段范围:RECORD/DETAIL/ACCOUNT',
    `field_name`          VARCHAR(128) NOT NULL COMMENT '字段名',
    `field_label`         VARCHAR(255) DEFAULT NULL COMMENT '字段中文名',

    `source_value`        TEXT COMMENT '来源原始值',
    `current_value`       TEXT COMMENT '当前值/覆盖后的值',
    `is_overridden`       TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否被覆盖:0否1是',
    `override_reason`     VARCHAR(255) DEFAULT NULL COMMENT '修改原因',
    `override_type`       VARCHAR(32) DEFAULT NULL COMMENT '修改类型:MANUAL_FIX/SYSTEM_FIX/DATA_CLEAN/FIELD_MAPPING',

    `operator_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`       VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_field_name` (`field_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备字段覆盖修改表';


-- =========================================================
-- 5. 报备文件表
-- OA来源文件只读不可替换;ZPY来源文件按本地规则维护
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_file`;
CREATE TABLE `bridge_filing_file`
(
    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',

    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `master_data_source`  VARCHAR(16) NOT NULL COMMENT '主数据来源:OA/ZPY',
    `file_source`         VARCHAR(16) NOT NULL COMMENT '文件来源:OA/ZPY/MANUAL',
    `file_category`       VARCHAR(32) NOT NULL COMMENT '文件类别:CONTRACT/REPORT/ATTACHMENT/OTHER',

    `source_file_id`      VARCHAR(128) DEFAULT NULL COMMENT '来源系统文件ID',
    `file_name`           VARCHAR(255) NOT NULL COMMENT '文件名',
    `file_ext`            VARCHAR(32) DEFAULT NULL COMMENT '扩展名',
    `file_size`           BIGINT UNSIGNED DEFAULT NULL COMMENT '文件大小,字节',
    `mime_type`           VARCHAR(128) DEFAULT NULL COMMENT 'MIME类型',
    `file_hash`           VARCHAR(128) DEFAULT NULL COMMENT '文件哈希值',

    `file_path`           VARCHAR(1000) DEFAULT NULL COMMENT '存储路径',
    `file_url`            VARCHAR(1000) DEFAULT NULL COMMENT '访问地址',

    `is_readonly`         TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否只读:0否1是',
    `is_replaceable`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许替换:0否1是',
    `file_status`         VARCHAR(32) NOT NULL DEFAULT 'ACTIVE' COMMENT '文件状态:ACTIVE/DELETED/INVALID',

    `remark`              VARCHAR(1000) DEFAULT NULL COMMENT '备注',
    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_file_source` (`file_source`),
    KEY `idx_file_category` (`file_category`),
    KEY `idx_master_data_source` (`master_data_source`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备文件表';


-- =========================================================
-- 6. 报备请求流水日志表
-- 记录OA推送、OA拉取、评协登录、评协提交、查询、回写等每一次请求
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_request_log`;
CREATE TABLE `bridge_filing_request_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备主表ID',
    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备明细ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) NOT NULL COMMENT '请求流水号',
    `parent_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '父请求流水号',

    `request_type`          VARCHAR(32) NOT NULL COMMENT '请求类型:OA_PUSH/OA_PULL_PROJECT/OA_PULL_CONTRACT/OA_PULL_REPORT/OA_PUSH_ACCOUNT/ASSOCIATION_LOGIN/ASSOCIATION_SUBMIT/ASSOCIATION_QUERY/CALLBACK/SYNC_BACK',
    `request_direction`     VARCHAR(16) NOT NULL COMMENT '方向:INBOUND/OUTBOUND/INTERNAL',
    `biz_stage`             VARCHAR(32) DEFAULT NULL COMMENT '业务阶段:FETCH_PROJECT/FETCH_CONTRACT/FETCH_REPORT/ACCOUNT_PREPARE/EDIT_DATA/SUBMIT_ASSOCIATION/QUERY_RESULT/SYNC_BACK',
    `data_snapshot_type`    VARCHAR(32) DEFAULT NULL COMMENT '数据快照类型:SOURCE/FINAL/FILE_ONLY/PARTIAL',

    `request_status`        VARCHAR(32) NOT NULL DEFAULT 'PROCESSING' COMMENT '请求状态:PROCESSING/SUCCESS/FAILED/IGNORED',

    `http_method`           VARCHAR(16) DEFAULT NULL COMMENT 'HTTP方法',
    `request_url`           VARCHAR(500) DEFAULT NULL COMMENT '请求地址',
    `request_headers`       JSON DEFAULT NULL COMMENT '请求头',
    `request_body`          JSON DEFAULT NULL COMMENT '请求体',
    `response_code`         VARCHAR(64) DEFAULT NULL COMMENT '响应码',
    `response_body`         JSON DEFAULT NULL COMMENT '响应体',

    `duration_ms`           INT DEFAULT NULL COMMENT '耗时毫秒',
    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_request_id` (`request_id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_parent_request_id` (`parent_request_id`),
    KEY `idx_request_type` (`request_type`),
    KEY `idx_request_status` (`request_status`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备请求流水日志表';


-- =========================================================
-- 7. 报备状态流转日志表
-- 记录状态变化过程,便于审计和排错
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_status_log`;
CREATE TABLE `bridge_filing_status_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `status_type`           VARCHAR(32) NOT NULL COMMENT '状态类型:FILING_STATUS/OA_DATA_STATUS/ASSOCIATION_STATUS/SYNC_STATUS/DETAIL_STATUS',
    `from_status`           VARCHAR(32) DEFAULT NULL COMMENT '原状态',
    `to_status`             VARCHAR(32) NOT NULL COMMENT '新状态',
    `trigger_type`          VARCHAR(32) DEFAULT NULL COMMENT '触发方式:REQUEST_RESPONSE/MANUAL_EDIT/SYSTEM_RETRY/AUTO_SYNC',

    `change_reason`         VARCHAR(255) DEFAULT NULL COMMENT '变更原因',
    `change_code`           VARCHAR(64) DEFAULT NULL COMMENT '变更码',
    `change_msg`            VARCHAR(1000) DEFAULT NULL COMMENT '变更说明',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_status_type` (`status_type`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备状态流转日志表';


-- =========================================================
-- 8. 评协交互日志表
-- 专门记录与评协系统的登录、提交、查询、补件、人工备注、沟通等
-- =========================================================
DROP TABLE IF EXISTS `bridge_filing_association_log`;
CREATE TABLE `bridge_filing_association_log`
(
    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',
    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',
    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',

    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路追踪号',
    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',

    `action_type`           VARCHAR(32) NOT NULL COMMENT '动作类型:LOGIN/SUBMIT/RESUBMIT/QUERY/UPLOAD_ATTACHMENT/MANUAL_NOTE/CALL_ASSOCIATION/EMAIL_ASSOCIATION/OTHER',
    `action_status`         VARCHAR(32) NOT NULL DEFAULT 'SUCCESS' COMMENT '动作状态:SUCCESS/FAILED/PENDING',
    `association_account`   VARCHAR(255) DEFAULT NULL COMMENT '使用的评协账号,可脱敏',

    `content`               VARCHAR(2000) DEFAULT NULL COMMENT '动作说明/沟通内容',
    `request_body`          JSON DEFAULT NULL COMMENT '请求体',
    `response_body`         JSON DEFAULT NULL COMMENT '响应体',
    `attachment_json`       JSON DEFAULT NULL COMMENT '附件信息',
    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',
    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',
    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',
    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`),
    KEY `idx_filing_record_id` (`filing_record_id`),
    KEY `idx_filing_detail_id` (`filing_detail_id`),
    KEY `idx_trace_id` (`trace_id`),
    KEY `idx_request_id` (`request_id`),
    KEY `idx_action_type` (`action_type`),
    KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评协交互日志表';

SET FOREIGN_KEY_CHECKS = 1;

三、这套表怎么理解,给你说透

1. bridge_filing_record 是总单

一笔报备就是一条主记录。

你以后查一笔报备,先看这张表。

这张表解决的是:

这笔报备是谁发起的
来自 OA 还是来自我们系统
主数据来源是谁
编辑策略是什么
是否依赖 OA 项目、合同、报告
是否依赖本地底稿
用了哪套评协账号
最终状态是什么
最终提交评协时用了什么快照

这里最关键的几个字段是:

filing_initiator

是谁发起动作的。

filing_mode

这笔报备走的是哪种业务模式。

master_data_source

这笔报备的数据到底以谁为准。

data_edit_policy

来自 OA 时,结构化字段可改但文件只读;来自我方时,按我方规则走。

source_snapshot_json

把来源系统的原始数据快照留住。

submit_snapshot_json

把最终真正提交评协的数据留住。

这两个快照非常重要。

没有它们,后面你根本说不清:
为什么原来 OA 是这个值,最终提交却变成另一个值。

2. bridge_filing_detail 是明细

一笔报备可能不止一个合同,不止一个报告,不止一个明细项。

所以要拆明细。

这张表负责:

合同编号
报告号
项目名称
委托方
签字评估师
本明细是否改过
本明细原始快照和最终快照

3. bridge_filing_field_override 是改动痕迹表

这是你这次需求里很关键的一张表。

因为你已经明确:
来自 OA 的信息在我们这里可以修改。

那就不能只保存“最后改完的值”,必须保存:

原始值
当前值
谁改的
为什么改

否则你后面很难追责,也很难排错。

比如:

OA 推来委托方名是“湖北某某有限公司”
我们本地改成“湖北某某集团有限公司”

那这张表就记一条。

4. bridge_filing_file 是文件表

你已经定了:
来自 OA 的文件不可修改。

那这就不能只在业务代码里“约定一下”,必须落表控制。

所以这张表里有:

file_source
文件来源

is_readonly
是否只读

is_replaceable
是否允许替换

对于 OA 文件,建议固定写成:

file_source = OA
is_readonly = 1
is_replaceable = 0

这样前端、后端、接口层都能统一处理。

5. bridge_filing_request_log 是请求流水

这张表不是只给接口日志用的,它是整条链路的骨架。

比如:

OA 推送项目
我方拉取合同
我方拉取报告
OA 推送评协账号
登录评协
提交评协
查询评协结果
回写结果给 OA

每一步都可以是一条请求流水。

后面你查问题,先按 trace_id 一串,就全出来了。

6. bridge_filing_status_log 是状态变化历史

主表只存“当前状态”。

这张表存“怎么一步步变成当前状态”。

比如:

PENDING -> WAITING_DATA
WAITING_DATA -> EDITING
EDITING -> READY
READY -> SUBMITTING
SUBMITTING -> FAILED

这样后面才能完整复盘。

7. bridge_filing_association_log 是评协专属日志

这张表专门记录和评协的交互,不跟普通请求日志混在一起。

因为评协这块除了接口调用,还可能有:

人工电话沟通
补件
补充说明
二次提交
邮件沟通
备注说明

这些都适合记在这张表里。

四、你现在这套业务,推荐枚举值怎么统一

下面这些值,我建议你们团队后面直接统一,不要有人写 DONE,有人写 SUCCESS,有人写 OK

1. master_data_source

OA
ZPY

2. data_edit_policy

OA_EDITABLE_FILE_READONLY
ZPY_EDITABLE
READONLY

3. filing_initiator

OA_PUSH
ZPY_PULL
ZPY_MANUAL
SYSTEM_AUTO

4. filing_mode

OA_FULL_DATA
OA_PROJECT_PULL
ZPY_SELF_DATA
MANUAL_FILL
NO_DRAFT_REQUIRED

5. filing_status

PENDING
WAITING_DATA
EDITING
READY
SUBMITTING
SUBMITTED
SUCCESS
FAILED
CANCELLED

6. oa_data_status

NOT_REQUIRED
PENDING
PARTIAL
READY
FAILED

7. association_status

NOT_SUBMITTED
SUBMITTING
SUBMITTED
SUCCESS
FAILED

8. sync_status

NOT_REQUIRED
PENDING
SUCCESS
FAILED

五、给你几个典型业务场景,便于你验证设计是不是贴合

场景一:OA 推完整资料给你,你直接报备

主表建议这样:

filing_initiator = OA_PUSH
filing_mode = OA_FULL_DATA
master_data_source = OA
data_edit_policy = OA_EDITABLE_FILE_READONLY
need_oa_project = 1
need_oa_contract = 1
need_oa_report = 1
need_local_draft = 0

文件表里:
OA 文件全部只读不可替换。

如果用户改了委托方名称,就进 bridge_filing_field_override

场景二:你主动拉 OA 的立项、合同、报告后报备

filing_initiator = ZPY_PULL
filing_mode = OA_PROJECT_PULL
master_data_source = OA
data_edit_policy = OA_EDITABLE_FILE_READONLY

虽然是你发起拉取,但数据主来源仍然是 OA。

这一点正是 filing_initiatormaster_data_source 不能混为一谈的原因。

场景三:完全用你们系统的数据报备

filing_initiator = ZPY_MANUAL
filing_mode = ZPY_SELF_DATA
master_data_source = ZPY
data_edit_policy = ZPY_EDITABLE

此时文件、账号、项目资料全部按你们自己系统走。

场景四:不依赖你们系统底稿完成报备

filing_mode = NO_DRAFT_REQUIRED
need_local_draft = 0

但主来源仍可分 OA 或 ZPY。

六、我帮你再提三个落地建议

1. 密码不要明文存

你这块一定别图省事,别存 login_password 明文。

现在我给你的是:
login_password_enc

你后面自己做对称加密存储,提交时解密。

2. trace_idrequest_id 一定统一生成规则

建议:

trace_id
一笔报备从头到尾不变

request_id
每个动作一条新的

这样整个排错链路才顺。

3. 文件只读不仅要落表,还要落代码

也就是:

数据库里有 is_readonly = 1
前端按钮禁用
后端接口校验拒绝
服务层校验拒绝

否则光表里记着没用。

七、如果从“精简可上线”的角度看,哪些表最核心

如果你现在想先快速上线,最少应该先上这六张:

bridge_filing_record
bridge_filing_detail
bridge_filing_field_override
bridge_filing_file
bridge_filing_request_log
bridge_filing_status_log

这六张已经足够形成完整主链路。

如果再进一步完善,就加:

bridge_filing_account
bridge_filing_association_log

八、最后我直接给你一句总评

这套设计的核心,不再是“建两个报备表”,而是把报备做成一条完整、可追踪、可审计、可覆盖修改、可还原快照的数据链。

它能解决的不是单纯存数据,而是解决你后面最麻烦的三件事:

到底这笔报备用的是谁的数据
来源数据后来被谁改过
最终提交评协时到底交了什么

这三件事能说明白,这套设计基本就稳了。

下一步我可以继续直接给你补两样东西之一:

第一,基于这套表,继续帮你输出一份“字段枚举值说明文档”。
第二,继续帮你按你们 PHP/Yii2 的风格,生成对应的 AR Model 名称建议和建表迁移文件结构。

我问:

local_project_id这个得改成项目组id,我们是以项目组为单位提交审核及报备的。

filing_initiator这个里面报备就oa推送,我们系统手动提交报备两种。

filing_mode这个我觉得一个是oa推送,一个是我们拉取,一个是我们系统完成的报告提交,一个是线下完成的报告提交4种,你分的感觉不对。因此master_data_source似乎不必要。

data_edit_policy这个似乎也无必要,无论是我们系统还是oa系统数据都可以编辑。

`need_oa_project`       TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA立项信息:0否1是',

`need_oa_contract`      TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA合同信息:0否1是',

`need_oa_report`        TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否依赖OA报告信息:0否1是',

`need_local_draft`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否依赖我方报告底稿:0否1是',

以上四个似乎也不必要。里面的数据快照和请求数据体,因为我有文件你怎么快照,请你考虑这个因素再增强这个表。另外交互的部分需要加入超时的状态。

bridge_filing_detail这里的项目名改成项目组名。is_editable这个不必要。

我报告、合同、账号是一起拉取或者oa推送的,因此你分的阶段不要太细了。

data_snapshot_type这个类型不需要分太细。

请记住设计表不能太过细致了。让系统过于复杂。请你基于这个原则做一下优化。而且报备没有回调,都是及时响应。请你考虑。

bridge_filing_status_log这张表里面变更等,我们没有变更。请你重新考虑。

你只需要输出sql就行,不需要其他解释。

AI答:

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;


-- =========================================================

-- 1. 报备主表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_record`;

CREATE TABLE `bridge_filing_record`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '整笔报备链路号',

    `latest_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '最新请求流水号',


    `oa_project_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT 'OA项目ID',

    `oa_project_code`       VARCHAR(128) DEFAULT NULL COMMENT 'OA项目编号',

    `project_group_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '项目组ID',

    `submission_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '提交记录ID/提审记录ID',


    `filing_no`             VARCHAR(64) DEFAULT NULL COMMENT '我方报备编号',

    `external_filing_no`    VARCHAR(128) DEFAULT NULL COMMENT '外部系统返回的报备号/备案号',


    `filing_initiator`      VARCHAR(32) NOT NULL COMMENT '报备发起方:OA_PUSH/ZPY_MANUAL',

    `filing_mode`           VARCHAR(32) NOT NULL COMMENT '报备方式:OA_PUSH/ZPY_PULL/ZPY_REPORT/OFFLINE_REPORT',


    `account_source`        VARCHAR(32) DEFAULT NULL COMMENT '评协账号来源:OA_PUSH/ZPY_PULL/LOCAL_CONFIG/USER_INPUT/TEMP_INPUT',

    `account_config_id`     BIGINT UNSIGNED DEFAULT NULL COMMENT '使用的本地账号配置ID',


    `source_data_json`      JSON DEFAULT NULL COMMENT '来源业务数据JSON快照,不含文件二进制',

    `submit_data_json`      JSON DEFAULT NULL COMMENT '最终提交业务数据JSON快照,不含文件二进制',

    `account_snapshot_json` JSON DEFAULT NULL COMMENT '本次使用账号快照,建议脱敏存储',


    `has_field_override`    TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在字段覆盖修改:0否1是',

    `has_file`              TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否有文件:0否1是',


    `filing_status`         VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '报备状态:PENDING/EDITING/READY/SUBMITTING/SUBMITTED/SUCCESS/FAILED/TIMEOUT/CANCELLED',

    `association_status`    VARCHAR(32) DEFAULT NULL COMMENT '评协状态:NOT_SUBMITTED/SUBMITTING/SUBMITTED/SUCCESS/FAILED/TIMEOUT',


    `filing_result_code`    VARCHAR(64) DEFAULT NULL COMMENT '结果码',

    `filing_result_msg`     VARCHAR(1000) DEFAULT NULL COMMENT '结果说明',


    `request_body`          JSON DEFAULT NULL COMMENT '创建报备时原始请求体,不含文件二进制',

    `response_body`         JSON DEFAULT NULL COMMENT '创建报备时原始响应体',

    `remark`                VARCHAR(1000) DEFAULT NULL COMMENT '备注',


    `created_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',

    `updated_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',

    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    UNIQUE KEY `uk_trace_id` (`trace_id`),

    KEY `idx_partner_id` (`partner_id`),

    KEY `idx_enterprise_id` (`enterprise_id`),

    KEY `idx_submission_id` (`submission_id`),

    KEY `idx_oa_project_id` (`oa_project_id`),

    KEY `idx_project_group_id` (`project_group_id`),

    KEY `idx_filing_status` (`filing_status`),

    KEY `idx_association_status` (`association_status`),

    KEY `idx_filing_initiator` (`filing_initiator`),

    KEY `idx_filing_mode` (`filing_mode`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备主表';



-- =========================================================

-- 2. 报备详情表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_detail`;

CREATE TABLE `bridge_filing_detail`

(

    `id`                     BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `filing_record_id`       BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `detail_no`              INT NOT NULL DEFAULT 1 COMMENT '明细序号',


    `project_group_name`     VARCHAR(255) DEFAULT NULL COMMENT '项目组名称',


    `contract_id`            BIGINT UNSIGNED DEFAULT NULL COMMENT '合同ID',

    `contract_no`            VARCHAR(128) DEFAULT NULL COMMENT '合同编号',

    `contract_name`          VARCHAR(255) DEFAULT NULL COMMENT '合同名称',


    `report_id`              BIGINT UNSIGNED DEFAULT NULL COMMENT '报告ID',

    `report_no`              VARCHAR(128) DEFAULT NULL COMMENT '报告号',

    `report_name`            VARCHAR(255) DEFAULT NULL COMMENT '报告名称',


    `client_name`            VARCHAR(255) DEFAULT NULL COMMENT '委托方名称',

    `sign_appraiser_names`   VARCHAR(500) DEFAULT NULL COMMENT '签字评估师姓名,多个逗号分隔',


    `detail_status`          VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '明细状态:PENDING/READY/SUCCESS/FAILED/TIMEOUT',

    `error_code`             VARCHAR(64) DEFAULT NULL COMMENT '错误码',

    `error_msg`              VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',


    `request_id`             VARCHAR(64) DEFAULT NULL COMMENT '相关请求流水号',

    `source_detail_json`     JSON DEFAULT NULL COMMENT '来源明细JSON快照,不含文件二进制',

    `final_detail_json`      JSON DEFAULT NULL COMMENT '最终提交明细JSON快照,不含文件二进制',

    `detail_json`            JSON DEFAULT NULL COMMENT '扩展数据',


    `created_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`             DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_contract_no` (`contract_no`),

    KEY `idx_report_no` (`report_no`),

    KEY `idx_request_id` (`request_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备详情表';



-- =========================================================

-- 3. 企业评协账号配置表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_account`;

CREATE TABLE `bridge_filing_account`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',


    `account_source`        VARCHAR(32) NOT NULL COMMENT '账号来源:OA_PUSH/ZPY_PULL/LOCAL_CONFIG/USER_INPUT',

    `association_org_name`  VARCHAR(255) DEFAULT NULL COMMENT '评协机构/企业名称',

    `login_username`        VARCHAR(255) NOT NULL COMMENT '登录账号',

    `login_password_enc`    VARCHAR(1000) DEFAULT NULL COMMENT '加密后的登录密码',

    `password_updated_at`   DATETIME DEFAULT NULL COMMENT '密码更新时间',


    `is_default`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认账号',

    `is_valid`              TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否有效',

    `last_verify_status`    VARCHAR(32) DEFAULT NULL COMMENT '最近校验状态:UNKNOWN/SUCCESS/FAILED/TIMEOUT',

    `last_verify_msg`       VARCHAR(1000) DEFAULT NULL COMMENT '最近校验说明',


    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '来源对应请求流水号',

    `ext_json`              JSON DEFAULT NULL COMMENT '扩展数据',

    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_tenant_partner_enterprise` (`tenant_id`, `partner_id`, `enterprise_id`),

    KEY `idx_login_username` (`login_username`),

    KEY `idx_request_id` (`request_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业评协账号配置表';



-- =========================================================

-- 4. 报备字段覆盖修改表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_field_override`;

CREATE TABLE `bridge_filing_field_override`

(

    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID,可为空',


    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `field_scope`         VARCHAR(32) NOT NULL COMMENT '字段范围:RECORD/DETAIL/ACCOUNT',

    `field_name`          VARCHAR(128) NOT NULL COMMENT '字段名',

    `field_label`         VARCHAR(255) DEFAULT NULL COMMENT '字段中文名',


    `source_value`        TEXT COMMENT '来源原始值',

    `current_value`       TEXT COMMENT '当前值',

    `override_reason`     VARCHAR(255) DEFAULT NULL COMMENT '修改原因',

    `operator_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`       VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',

    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_field_name` (`field_name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备字段覆盖修改表';



-- =========================================================

-- 5. 报备文件表

-- 文件快照只记录元数据,不保存文件二进制

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_file`;

CREATE TABLE `bridge_filing_file`

(

    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',


    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `file_source`         VARCHAR(16) NOT NULL COMMENT '文件来源:OA/ZPY/MANUAL',

    `file_category`       VARCHAR(32) NOT NULL COMMENT '文件类别:CONTRACT/REPORT/ATTACHMENT/OTHER',


    `source_file_id`      VARCHAR(128) DEFAULT NULL COMMENT '来源系统文件ID',

    `file_name`           VARCHAR(255) NOT NULL COMMENT '文件名',

    `file_ext`            VARCHAR(32) DEFAULT NULL COMMENT '扩展名',

    `file_size`           BIGINT UNSIGNED DEFAULT NULL COMMENT '文件大小,字节',

    `mime_type`           VARCHAR(128) DEFAULT NULL COMMENT 'MIME类型',

    `file_hash`           VARCHAR(128) DEFAULT NULL COMMENT '文件哈希值',


    `file_path`           VARCHAR(1000) DEFAULT NULL COMMENT '存储路径',

    `file_url`            VARCHAR(1000) DEFAULT NULL COMMENT '访问地址',


    `is_readonly`         TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否只读:0否1是',

    `is_replaceable`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许替换:0否1是',

    `file_status`         VARCHAR(32) NOT NULL DEFAULT 'ACTIVE' COMMENT '文件状态:ACTIVE/DELETED/INVALID',


    `remark`              VARCHAR(1000) DEFAULT NULL COMMENT '备注',

    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_file_source` (`file_source`),

    KEY `idx_file_category` (`file_category`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备文件表';



-- =========================================================

-- 6. 报备请求流水日志表

-- 记录OA推送、我方拉取、评协提交等;无回调,均为即时响应

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_request_log`;

CREATE TABLE `bridge_filing_request_log`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备主表ID',

    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备明细ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`            VARCHAR(64) NOT NULL COMMENT '请求流水号',

    `parent_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '父请求流水号',


    `request_type`          VARCHAR(32) NOT NULL COMMENT '请求类型:OA_PUSH/ZPY_PULL/ASSOCIATION_SUBMIT/ASSOCIATION_QUERY/INTERNAL',

    `request_direction`     VARCHAR(16) NOT NULL COMMENT '方向:INBOUND/OUTBOUND/INTERNAL',

    `biz_stage`             VARCHAR(32) DEFAULT NULL COMMENT '业务阶段:RECEIVE_DATA/PULL_DATA/SUBMIT_ASSOCIATION/QUERY_RESULT',

    `data_snapshot_type`    VARCHAR(16) DEFAULT NULL COMMENT '数据快照类型:SOURCE/FINAL',


    `request_status`        VARCHAR(32) NOT NULL DEFAULT 'PROCESSING' COMMENT '请求状态:PROCESSING/SUCCESS/FAILED/TIMEOUT/IGNORED',


    `http_method`           VARCHAR(16) DEFAULT NULL COMMENT 'HTTP方法',

    `request_url`           VARCHAR(500) DEFAULT NULL COMMENT '请求地址',

    `request_headers`       JSON DEFAULT NULL COMMENT '请求头',

    `request_body`          JSON DEFAULT NULL COMMENT '请求体,不含文件二进制',

    `response_code`         VARCHAR(64) DEFAULT NULL COMMENT '响应码',

    `response_body`         JSON DEFAULT NULL COMMENT '响应体',


    `duration_ms`           INT DEFAULT NULL COMMENT '耗时毫秒',

    `timeout_ms`            INT DEFAULT NULL COMMENT '超时阈值毫秒',

    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',

    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',


    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',

    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`),

    UNIQUE KEY `uk_request_id` (`request_id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_parent_request_id` (`parent_request_id`),

    KEY `idx_request_type` (`request_type`),

    KEY `idx_request_status` (`request_status`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备请求流水日志表';



-- =========================================================

-- 7. 评协交互日志表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_association_log`;

CREATE TABLE `bridge_filing_association_log`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `action_type`           VARCHAR(32) NOT NULL COMMENT '动作类型:LOGIN/SUBMIT/QUERY/MANUAL_NOTE/OTHER',

    `action_status`         VARCHAR(32) NOT NULL DEFAULT 'SUCCESS' COMMENT '动作状态:SUCCESS/FAILED/TIMEOUT/PENDING',

    `association_account`   VARCHAR(255) DEFAULT NULL COMMENT '使用的评协账号,可脱敏',


    `content`               VARCHAR(2000) DEFAULT NULL COMMENT '动作说明/沟通内容',

    `request_body`          JSON DEFAULT NULL COMMENT '请求体,不含文件二进制',

    `response_body`         JSON DEFAULT NULL COMMENT '响应体',

    `attachment_json`       JSON DEFAULT NULL COMMENT '附件元数据',

    `timeout_ms`            INT DEFAULT NULL COMMENT '超时阈值毫秒',

    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',

    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',


    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',

    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_action_type` (`action_type`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评协交互日志表';


SET FOREIGN_KEY_CHECKS = 1;

我问:

USER_INPUT/TEMP_INPUT这俩没区别,去掉后者。

`has_file`              TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否有文件:0否1是',

以上两个不需要。

CANCELLED似乎不需要,我们不提供取消报备,一旦提交这次流程就要执行到底。

`detail_status`          VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '明细状态:PENDING/READY/SUCCESS/FAILED/TIMEOUT',

`error_code`             VARCHAR(64) DEFAULT NULL COMMENT '错误码',

`error_msg`              VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',

这三没必要。

另外报备信息还是得允许删除,相关字段也加上。

bridge_filing_detail这个表里的报告其实是项目组主体,把报告和项目组这个信息都反应在字段里。

AI答:

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;


-- =========================================================

-- 1. 报备主表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_record`;

CREATE TABLE `bridge_filing_record`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '整笔报备链路号',

    `latest_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '最新请求流水号',


    `oa_project_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT 'OA项目ID',

    `oa_project_code`       VARCHAR(128) DEFAULT NULL COMMENT 'OA项目编号',

    `project_group_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '项目组ID',

    `submission_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '提交记录ID/提审记录ID',


    `filing_no`             VARCHAR(64) DEFAULT NULL COMMENT '我方报备编号',

    `external_filing_no`    VARCHAR(128) DEFAULT NULL COMMENT '外部系统返回的报备号/备案号',


    `filing_initiator`      VARCHAR(32) NOT NULL COMMENT '报备发起方:OA_PUSH/ZPY_MANUAL',

    `filing_mode`           VARCHAR(32) NOT NULL COMMENT '报备方式:OA_PUSH/ZPY_PULL/ZPY_REPORT/OFFLINE_REPORT',


    `account_source`        VARCHAR(32) DEFAULT NULL COMMENT '评协账号来源:OA_PUSH/ZPY_PULL/LOCAL_CONFIG/USER_INPUT',

    `account_config_id`     BIGINT UNSIGNED DEFAULT NULL COMMENT '使用的本地账号配置ID',


    `source_data_json`      JSON DEFAULT NULL COMMENT '来源业务数据JSON快照,不含文件二进制',

    `submit_data_json`      JSON DEFAULT NULL COMMENT '最终提交业务数据JSON快照,不含文件二进制',

    `account_snapshot_json` JSON DEFAULT NULL COMMENT '本次使用账号快照,建议脱敏存储',


    `has_field_override`    TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否存在字段覆盖修改:0否1是',


    `filing_status`         VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '报备状态:PENDING/EDITING/READY/SUBMITTING/SUBMITTED/SUCCESS/FAILED/TIMEOUT',

    `association_status`    VARCHAR(32) DEFAULT NULL COMMENT '评协状态:NOT_SUBMITTED/SUBMITTING/SUBMITTED/SUCCESS/FAILED/TIMEOUT',


    `filing_result_code`    VARCHAR(64) DEFAULT NULL COMMENT '结果码',

    `filing_result_msg`     VARCHAR(1000) DEFAULT NULL COMMENT '结果说明',


    `request_body`          JSON DEFAULT NULL COMMENT '创建报备时原始请求体,不含文件二进制',

    `response_body`         JSON DEFAULT NULL COMMENT '创建报备时原始响应体',

    `remark`                VARCHAR(1000) DEFAULT NULL COMMENT '备注',


    `is_deleted`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`            DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',

    `updated_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',

    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    UNIQUE KEY `uk_trace_id` (`trace_id`),

    KEY `idx_partner_id` (`partner_id`),

    KEY `idx_enterprise_id` (`enterprise_id`),

    KEY `idx_submission_id` (`submission_id`),

    KEY `idx_oa_project_id` (`oa_project_id`),

    KEY `idx_project_group_id` (`project_group_id`),

    KEY `idx_filing_status` (`filing_status`),

    KEY `idx_association_status` (`association_status`),

    KEY `idx_filing_initiator` (`filing_initiator`),

    KEY `idx_filing_mode` (`filing_mode`),

    KEY `idx_is_deleted` (`is_deleted`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备主表';



-- =========================================================

-- 2. 报备详情表

-- 报告主体按项目组维度体现

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_detail`;

CREATE TABLE `bridge_filing_detail`

(

    `id`                        BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `filing_record_id`          BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `detail_no`                 INT NOT NULL DEFAULT 1 COMMENT '明细序号',


    `project_group_id`          BIGINT UNSIGNED DEFAULT NULL COMMENT '项目组ID',

    `project_group_name`        VARCHAR(255) DEFAULT NULL COMMENT '项目组名称',

    `project_group_code`        VARCHAR(128) DEFAULT NULL COMMENT '项目组编号',


    `report_project_group_id`   BIGINT UNSIGNED DEFAULT NULL COMMENT '报告所属项目组ID',

    `report_project_group_name` VARCHAR(255) DEFAULT NULL COMMENT '报告所属项目组名称',

    `report_project_group_code` VARCHAR(128) DEFAULT NULL COMMENT '报告所属项目组编号',


    `contract_id`               BIGINT UNSIGNED DEFAULT NULL COMMENT '合同ID',

    `contract_no`               VARCHAR(128) DEFAULT NULL COMMENT '合同编号',

    `contract_name`             VARCHAR(255) DEFAULT NULL COMMENT '合同名称',


    `report_id`                 BIGINT UNSIGNED DEFAULT NULL COMMENT '报告ID',

    `report_no`                 VARCHAR(128) DEFAULT NULL COMMENT '报告号',

    `report_name`               VARCHAR(255) DEFAULT NULL COMMENT '报告名称',


    `client_name`               VARCHAR(255) DEFAULT NULL COMMENT '委托方名称',

    `sign_appraiser_names`      VARCHAR(500) DEFAULT NULL COMMENT '签字评估师姓名,多个逗号分隔',


    `request_id`                VARCHAR(64) DEFAULT NULL COMMENT '相关请求流水号',

    `source_detail_json`        JSON DEFAULT NULL COMMENT '来源明细JSON快照,不含文件二进制',

    `final_detail_json`         JSON DEFAULT NULL COMMENT '最终提交明细JSON快照,不含文件二进制',

    `detail_json`               JSON DEFAULT NULL COMMENT '扩展数据',


    `is_deleted`                TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`                BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`                DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`                DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`                DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_project_group_id` (`project_group_id`),

    KEY `idx_report_project_group_id` (`report_project_group_id`),

    KEY `idx_contract_no` (`contract_no`),

    KEY `idx_report_no` (`report_no`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_is_deleted` (`is_deleted`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备详情表';



-- =========================================================

-- 3. 企业评协账号配置表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_account`;

CREATE TABLE `bridge_filing_account`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `enterprise_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '企业ID',


    `account_source`        VARCHAR(32) NOT NULL COMMENT '账号来源:OA_PUSH/ZPY_PULL/LOCAL_CONFIG/USER_INPUT',

    `association_org_name`  VARCHAR(255) DEFAULT NULL COMMENT '评协机构/企业名称',

    `login_username`        VARCHAR(255) NOT NULL COMMENT '登录账号',

    `login_password_enc`    VARCHAR(1000) DEFAULT NULL COMMENT '加密后的登录密码',

    `password_updated_at`   DATETIME DEFAULT NULL COMMENT '密码更新时间',


    `is_default`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认账号',

    `is_valid`              TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否有效',

    `last_verify_status`    VARCHAR(32) DEFAULT NULL COMMENT '最近校验状态:UNKNOWN/SUCCESS/FAILED/TIMEOUT',

    `last_verify_msg`       VARCHAR(1000) DEFAULT NULL COMMENT '最近校验说明',


    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '来源对应请求流水号',

    `ext_json`              JSON DEFAULT NULL COMMENT '扩展数据',


    `is_deleted`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`            DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_tenant_partner_enterprise` (`tenant_id`, `partner_id`, `enterprise_id`),

    KEY `idx_login_username` (`login_username`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_is_deleted` (`is_deleted`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业评协账号配置表';



-- =========================================================

-- 4. 报备字段覆盖修改表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_field_override`;

CREATE TABLE `bridge_filing_field_override`

(

    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID,可为空',


    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `field_scope`         VARCHAR(32) NOT NULL COMMENT '字段范围:RECORD/DETAIL/ACCOUNT',

    `field_name`          VARCHAR(128) NOT NULL COMMENT '字段名',

    `field_label`         VARCHAR(255) DEFAULT NULL COMMENT '字段中文名',


    `source_value`        TEXT COMMENT '来源原始值',

    `current_value`       TEXT COMMENT '当前值',

    `override_reason`     VARCHAR(255) DEFAULT NULL COMMENT '修改原因',

    `operator_id`         BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`       VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',


    `is_deleted`          TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`          BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`          DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_field_name` (`field_name`),

    KEY `idx_is_deleted` (`is_deleted`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备字段覆盖修改表';



-- =========================================================

-- 5. 报备文件表

-- 文件快照只记录元数据,不保存文件二进制

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_file`;

CREATE TABLE `bridge_filing_file`

(

    `id`                  BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`           BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`          BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`    BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`    BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',


    `trace_id`            VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`          VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `file_source`         VARCHAR(16) NOT NULL COMMENT '文件来源:OA/ZPY/MANUAL',

    `file_category`       VARCHAR(32) NOT NULL COMMENT '文件类别:CONTRACT/REPORT/ATTACHMENT/OTHER',


    `source_file_id`      VARCHAR(128) DEFAULT NULL COMMENT '来源系统文件ID',

    `file_name`           VARCHAR(255) NOT NULL COMMENT '文件名',

    `file_ext`            VARCHAR(32) DEFAULT NULL COMMENT '扩展名',

    `file_size`           BIGINT UNSIGNED DEFAULT NULL COMMENT '文件大小,字节',

    `mime_type`           VARCHAR(128) DEFAULT NULL COMMENT 'MIME类型',

    `file_hash`           VARCHAR(128) DEFAULT NULL COMMENT '文件哈希值',


    `file_path`           VARCHAR(1000) DEFAULT NULL COMMENT '存储路径',

    `file_url`            VARCHAR(1000) DEFAULT NULL COMMENT '访问地址',


    `is_readonly`         TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否只读:0否1是',

    `is_replaceable`      TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许替换:0否1是',

    `file_status`         VARCHAR(32) NOT NULL DEFAULT 'ACTIVE' COMMENT '文件状态:ACTIVE/DELETED/INVALID',


    `remark`              VARCHAR(1000) DEFAULT NULL COMMENT '备注',


    `is_deleted`          TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`          BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`          DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `updated_at`          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_file_source` (`file_source`),

    KEY `idx_file_category` (`file_category`),

    KEY `idx_is_deleted` (`is_deleted`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备文件表';



-- =========================================================

-- 6. 报备请求流水日志表

-- 记录OA推送、我方拉取、评协提交等;无回调,均为即时响应

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_request_log`;

CREATE TABLE `bridge_filing_request_log`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备主表ID',

    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '关联报备明细ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`            VARCHAR(64) NOT NULL COMMENT '请求流水号',

    `parent_request_id`     VARCHAR(64) DEFAULT NULL COMMENT '父请求流水号',


    `request_type`          VARCHAR(32) NOT NULL COMMENT '请求类型:OA_PUSH/ZPY_PULL/ASSOCIATION_SUBMIT/ASSOCIATION_QUERY/INTERNAL',

    `request_direction`     VARCHAR(16) NOT NULL COMMENT '方向:INBOUND/OUTBOUND/INTERNAL',

    `biz_stage`             VARCHAR(32) DEFAULT NULL COMMENT '业务阶段:RECEIVE_DATA/PULL_DATA/SUBMIT_ASSOCIATION/QUERY_RESULT',

    `data_snapshot_type`    VARCHAR(16) DEFAULT NULL COMMENT '数据快照类型:SOURCE/FINAL',


    `request_status`        VARCHAR(32) NOT NULL DEFAULT 'PROCESSING' COMMENT '请求状态:PROCESSING/SUCCESS/FAILED/TIMEOUT/IGNORED',


    `http_method`           VARCHAR(16) DEFAULT NULL COMMENT 'HTTP方法',

    `request_url`           VARCHAR(500) DEFAULT NULL COMMENT '请求地址',

    `request_headers`       JSON DEFAULT NULL COMMENT '请求头',

    `request_body`          JSON DEFAULT NULL COMMENT '请求体,不含文件二进制',

    `response_code`         VARCHAR(64) DEFAULT NULL COMMENT '响应码',

    `response_body`         JSON DEFAULT NULL COMMENT '响应体',


    `duration_ms`           INT DEFAULT NULL COMMENT '耗时毫秒',

    `timeout_ms`            INT DEFAULT NULL COMMENT '超时阈值毫秒',

    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',

    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',


    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',


    `is_deleted`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`            DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`),

    UNIQUE KEY `uk_request_id` (`request_id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_parent_request_id` (`parent_request_id`),

    KEY `idx_request_type` (`request_type`),

    KEY `idx_request_status` (`request_status`),

    KEY `idx_is_deleted` (`is_deleted`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报备请求流水日志表';



-- =========================================================

-- 7. 评协交互日志表

-- =========================================================

DROP TABLE IF EXISTS `bridge_filing_association_log`;

CREATE TABLE `bridge_filing_association_log`

(

    `id`                    BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',

    `tenant_id`             BIGINT UNSIGNED NOT NULL COMMENT '租户ID',

    `partner_id`            BIGINT UNSIGNED NOT NULL COMMENT '对接方ID',

    `filing_record_id`      BIGINT UNSIGNED NOT NULL COMMENT '报备主表ID',

    `filing_detail_id`      BIGINT UNSIGNED DEFAULT NULL COMMENT '报备明细ID',


    `trace_id`              VARCHAR(64) NOT NULL COMMENT '链路号',

    `request_id`            VARCHAR(64) DEFAULT NULL COMMENT '请求流水号',


    `action_type`           VARCHAR(32) NOT NULL COMMENT '动作类型:LOGIN/SUBMIT/QUERY/MANUAL_NOTE/OTHER',

    `action_status`         VARCHAR(32) NOT NULL DEFAULT 'SUCCESS' COMMENT '动作状态:SUCCESS/FAILED/TIMEOUT/PENDING',

    `association_account`   VARCHAR(255) DEFAULT NULL COMMENT '使用的评协账号,可脱敏',


    `content`               VARCHAR(2000) DEFAULT NULL COMMENT '动作说明/沟通内容',

    `request_body`          JSON DEFAULT NULL COMMENT '请求体,不含文件二进制',

    `response_body`         JSON DEFAULT NULL COMMENT '响应体',

    `attachment_json`       JSON DEFAULT NULL COMMENT '附件元数据',

    `timeout_ms`            INT DEFAULT NULL COMMENT '超时阈值毫秒',

    `error_code`            VARCHAR(64) DEFAULT NULL COMMENT '错误码',

    `error_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '错误信息',


    `operator_id`           BIGINT UNSIGNED DEFAULT NULL COMMENT '操作人',

    `operator_name`         VARCHAR(128) DEFAULT NULL COMMENT '操作人名称',


    `is_deleted`            TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除:0否1是',

    `deleted_by`            BIGINT UNSIGNED DEFAULT NULL COMMENT '删除人',

    `deleted_at`            DATETIME DEFAULT NULL COMMENT '删除时间',


    `created_at`            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`),

    KEY `idx_filing_record_id` (`filing_record_id`),

    KEY `idx_filing_detail_id` (`filing_detail_id`),

    KEY `idx_trace_id` (`trace_id`),

    KEY `idx_request_id` (`request_id`),

    KEY `idx_action_type` (`action_type`),

    KEY `idx_is_deleted` (`is_deleted`),

    KEY `idx_created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评协交互日志表';


SET FOREIGN_KEY_CHECKS = 1;