-- ============================================================================ -- 开发环境初始化脚本 -- -- 执行时机:docker-entrypoint-initdb.d —— **仅在 MySQL 数据卷为空时的首次启动执行** -- 数据卷已存在时修改本文件不会生效,需要: -- docker compose -f docker/docker-compose.dev.yml down -v && up -d -- -- 内容 = db/migration/ 下**全部迁移**的最终结构(额外带 DROP,开发环境允许重置) -- 必须与 db/migration/V*.sql 的合集保持一致, -- 由 backend/tests/integration/test_schema_sync.py 自动校验,防止两份 DDL 漂移 -- -- 结尾写入 alembic_version 记录(**须等于当前 head**,否则开发库重建后 -- 执行 alembic upgrade head 会重复建表并报 1050 Table already exists) -- ============================================================================ SET NAMES utf8mb4; -- 删除顺序遵循外键依赖:先删子表 DROP TABLE IF EXISTS `param_values`; DROP TABLE IF EXISTS `param_change_batches`; DROP TABLE IF EXISTS `param_definitions`; DROP TABLE IF EXISTS `business_roles`; DROP TABLE IF EXISTS `operation_logs`; DROP TABLE IF EXISTS `role_permissions`; DROP TABLE IF EXISTS `user_roles`; DROP TABLE IF EXISTS `login_logs`; DROP TABLE IF EXISTS `permissions`; DROP TABLE IF EXISTS `users`; DROP TABLE IF EXISTS `roles`; DROP TABLE IF EXISTS `alembic_version`; -- 服务端字符集应为 utf8mb4 / utf8mb4_general_ci(与 compose 的启动参数一致) SELECT @@character_set_server AS charset, @@collation_server AS collation; -- --------------------------------------------------------------------------- -- 权限表 -- --------------------------------------------------------------------------- CREATE TABLE permissions ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, perm_code VARCHAR(128) NOT NULL COMMENT '权限编码,如 system:user:create', perm_name VARCHAR(64) NOT NULL COMMENT '权限名称', perm_type TINYINT NOT NULL COMMENT '类型:1菜单 2按钮 3接口' DEFAULT '1', parent_id BIGINT UNSIGNED COMMENT '父权限ID(permissions.id),顶级为空', sort_order INTEGER NOT NULL COMMENT '显示排序' DEFAULT '0', status TINYINT NOT NULL COMMENT '状态:1启用 0禁用' DEFAULT '1', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_permissions PRIMARY KEY (id), CONSTRAINT fk_permissions_parent_id FOREIGN KEY(parent_id) REFERENCES permissions (id) ON DELETE CASCADE, CONSTRAINT uk_permissions_perm_code UNIQUE (perm_code) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='权限表' COLLATE utf8mb4_general_ci; -- --------------------------------------------------------------------------- -- 角色表 -- --------------------------------------------------------------------------- CREATE TABLE roles ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, role_code VARCHAR(32) NOT NULL COMMENT '角色编码:admin系统管理员 user普通用户', role_name VARCHAR(64) NOT NULL COMMENT '角色名称', description VARCHAR(255) COMMENT '角色说明', sort_order INTEGER NOT NULL COMMENT '显示排序' DEFAULT '0', status TINYINT NOT NULL COMMENT '状态:1启用 0禁用' DEFAULT '1', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_roles PRIMARY KEY (id), CONSTRAINT uk_roles_role_code UNIQUE (role_code) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='角色表' COLLATE utf8mb4_general_ci; -- --------------------------------------------------------------------------- -- 系统用户表 -- --------------------------------------------------------------------------- CREATE TABLE users ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, username VARCHAR(64) NOT NULL COMMENT '登录用户名', password VARCHAR(100) NOT NULL COMMENT '密码哈希(BCrypt,固定60字符)', real_name VARCHAR(64) COMMENT '真实姓名', phone VARCHAR(20) COMMENT '手机号', email VARCHAR(128) COMMENT '邮箱', status TINYINT NOT NULL COMMENT '状态:1启用 0禁用' DEFAULT '1', token_version INTEGER NOT NULL COMMENT '令牌版本号:改密/禁用/强制下线时+1,使已签发Token立即失效' DEFAULT '1', last_login_time DATETIME COMMENT '最后登录时间', remark VARCHAR(255) COMMENT '备注', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_users PRIMARY KEY (id), CONSTRAINT uk_users_username UNIQUE (username) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='系统用户表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_users_phone ON users (phone); -- --------------------------------------------------------------------------- -- 登录日志表 -- --------------------------------------------------------------------------- CREATE TABLE login_logs ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, user_id BIGINT UNSIGNED COMMENT '用户ID(账号不存在时为空)', username VARCHAR(64) NOT NULL COMMENT '登录用户名(原样记录)', ip VARCHAR(45) COMMENT '客户端IP(45位兼容IPv6)', user_agent VARCHAR(255) COMMENT '客户端User-Agent(截断存储)', success TINYINT NOT NULL COMMENT '是否成功:1成功 0失败' DEFAULT '0', fail_reason VARCHAR(64) COMMENT '失败原因:验证码错误/用户名或密码错误/账号锁定/账号禁用', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_login_logs PRIMARY KEY (id), CONSTRAINT fk_login_logs_user_id FOREIGN KEY(user_id) REFERENCES users (id) ON DELETE SET NULL )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='登录日志表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_login_logs_create_time ON login_logs (create_time); CREATE INDEX idx_login_logs_username ON login_logs (username); -- --------------------------------------------------------------------------- -- 角色权限关联表 -- --------------------------------------------------------------------------- CREATE TABLE role_permissions ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID(roles.id)', permission_id BIGINT UNSIGNED NOT NULL COMMENT '权限ID(permissions.id)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_role_permissions PRIMARY KEY (id), CONSTRAINT fk_role_permissions_permission_id FOREIGN KEY(permission_id) REFERENCES permissions (id) ON DELETE CASCADE, CONSTRAINT fk_role_permissions_role_id FOREIGN KEY(role_id) REFERENCES roles (id) ON DELETE CASCADE, CONSTRAINT uk_role_permissions_role_id_permission_id UNIQUE (role_id, permission_id) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='角色权限关联表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_role_permissions_permission_id ON role_permissions (permission_id); -- --------------------------------------------------------------------------- -- 用户角色关联表 -- --------------------------------------------------------------------------- CREATE TABLE user_roles ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(users.id)', role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID(roles.id)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_user_roles PRIMARY KEY (id), CONSTRAINT fk_user_roles_role_id FOREIGN KEY(role_id) REFERENCES roles (id) ON DELETE CASCADE, CONSTRAINT fk_user_roles_user_id FOREIGN KEY(user_id) REFERENCES users (id) ON DELETE CASCADE, CONSTRAINT uk_user_roles_user_id_role_id UNIQUE (user_id, role_id) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='用户角色关联表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_user_roles_role_id ON user_roles (role_id); -- --------------------------------------------------------------------------- -- 操作日志表(V2 迁移) -- --------------------------------------------------------------------------- CREATE TABLE operation_logs ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, user_id BIGINT UNSIGNED COMMENT '操作人ID(账号删除后置空)', username VARCHAR(64) NOT NULL COMMENT '操作人用户名(冗余存储便于追溯)', module VARCHAR(64) NOT NULL COMMENT '所属模块,如 用户管理', action VARCHAR(32) NOT NULL COMMENT '操作类型:新增/修改/删除/导出', summary VARCHAR(255) NOT NULL COMMENT '操作摘要(中文,供人阅读)', method VARCHAR(8) COMMENT 'HTTP 方法', path VARCHAR(255) COMMENT '请求路径', ip VARCHAR(45) COMMENT '客户端IP(45位兼容IPv6)', user_agent VARCHAR(255) COMMENT '客户端User-Agent(截断存储)', request_data TEXT COMMENT '请求参数(已脱敏)', success TINYINT NOT NULL COMMENT '是否成功:1成功 0失败' DEFAULT '0', error_message VARCHAR(500) COMMENT '失败原因(写入方须截断)', duration_ms INTEGER COMMENT '处理耗时(毫秒)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_operation_logs PRIMARY KEY (id), CONSTRAINT fk_operation_logs_user_id FOREIGN KEY(user_id) REFERENCES users (id) ON DELETE SET NULL )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='操作日志表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_operation_logs_create_time ON operation_logs (create_time); CREATE INDEX idx_operation_logs_module ON operation_logs (module); CREATE INDEX idx_operation_logs_user_id ON operation_logs (user_id); CREATE INDEX idx_operation_logs_username ON operation_logs (username); -- --------------------------------------------------------------------------- -- 业务岗位角色表(V3 迁移) -- --------------------------------------------------------------------------- CREATE TABLE business_roles ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, role_code VARCHAR(32) NOT NULL COMMENT '岗位编码:salesperson营销员 sales_manager营销经理 info_officer信息员,创建后不可修改', role_name VARCHAR(64) NOT NULL COMMENT '岗位名称', calc_template VARCHAR(32) NOT NULL COMMENT '计提公式模板编码(以代码内模板注册表为准)', description VARCHAR(255) COMMENT '岗位说明', sort_order INTEGER NOT NULL COMMENT '显示排序' DEFAULT '0', status TINYINT NOT NULL COMMENT '状态:1启用 0禁用' DEFAULT '1', is_builtin TINYINT NOT NULL COMMENT '是否内置岗位:1内置(禁删禁停) 0自定义' DEFAULT '0', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_business_roles PRIMARY KEY (id), CONSTRAINT uk_business_roles_role_code UNIQUE (role_code) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='业务岗位角色表(与登录角色roles区分,决定计提公式与参数)' COLLATE utf8mb4_general_ci; -- --------------------------------------------------------------------------- -- 计提参数定义表(V3 迁移) -- --------------------------------------------------------------------------- CREATE TABLE param_definitions ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, param_code VARCHAR(64) NOT NULL COMMENT '参数编码,如 salesperson.rate.slope', param_name VARCHAR(64) NOT NULL COMMENT '参数名称', param_group VARCHAR(32) NOT NULL COMMENT '参数分组:业务员个人户/经理分成/企业户/信息员/支付环节/产品阈值/月工资口径', value_type VARCHAR(16) NOT NULL COMMENT '值类型:DECIMAL/INT/BOOL/ENUM/TEXT', unit VARCHAR(16) COMMENT '展示单位:‰/%/元/天,无单位为空', dimension_type VARCHAR(32) NOT NULL COMMENT '维度类型:NONE/PRODUCT_CATEGORY/BUSINESS_ROLE' DEFAULT 'NONE', options_text VARCHAR(255) COMMENT '枚举选项(竖线分隔),仅 ENUM 使用', default_value VARCHAR(64) COMMENT '系统默认值(Fraction 可解析字符串)', value_min VARCHAR(64) COMMENT '取值下限(含),校验用', value_max VARCHAR(64) COMMENT '取值上限(含),校验用', description VARCHAR(255) COMMENT '口径说明(配置页展示)', sort_order INTEGER NOT NULL COMMENT '显示排序' DEFAULT '0', status TINYINT NOT NULL COMMENT '状态:1启用 0停用' DEFAULT '1', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_param_definitions PRIMARY KEY (id), CONSTRAINT uk_param_definitions_param_code UNIQUE (param_code) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='计提参数定义表' COLLATE utf8mb4_general_ci; -- --------------------------------------------------------------------------- -- 参数变更批次表(V3 迁移) -- --------------------------------------------------------------------------- CREATE TABLE param_change_batches ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, version_no VARCHAR(32) NOT NULL COMMENT '版本号,如 P20261012-01', effective_date DATE NOT NULL COMMENT '生效日期(业务日期口径)', change_type TINYINT NOT NULL COMMENT '生效方式:1立即生效 2指定日期生效', remark VARCHAR(255) COMMENT '变更说明', operator_id BIGINT UNSIGNED COMMENT '操作人ID(账号删除后置空)', operator_name VARCHAR(64) NOT NULL COMMENT '操作人用户名(冗余固化)', item_count INTEGER NOT NULL COMMENT '变更参数项数' DEFAULT '0', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_param_change_batches PRIMARY KEY (id), CONSTRAINT fk_param_change_batches_operator_id FOREIGN KEY(operator_id) REFERENCES users (id) ON DELETE SET NULL, CONSTRAINT uk_param_change_batches_version_no UNIQUE (version_no) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='参数变更批次表' COLLATE utf8mb4_general_ci; -- --------------------------------------------------------------------------- -- 参数版本条目表(V3 迁移,append-only) -- --------------------------------------------------------------------------- CREATE TABLE param_values ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, param_id BIGINT UNSIGNED NOT NULL COMMENT '参数定义ID(param_definitions.id)', dimension_value VARCHAR(32) NOT NULL COMMENT '维度取值:NONE维度为空串;产品类别/岗位编码为具体值' DEFAULT '', effective_date DATE NOT NULL COMMENT '生效日期(按业务日期时点化取值)', value_text VARCHAR(64) NOT NULL COMMENT '参数值(Fraction 可解析字符串/枚举码/开关)', old_value_text VARCHAR(64) COMMENT '变更前值(留痕)', batch_id BIGINT UNSIGNED NOT NULL COMMENT '变更批次ID(param_change_batches.id)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_param_values PRIMARY KEY (id), CONSTRAINT fk_param_values_batch_id FOREIGN KEY(batch_id) REFERENCES param_change_batches (id) ON DELETE RESTRICT, CONSTRAINT fk_param_values_param_id FOREIGN KEY(param_id) REFERENCES param_definitions (id) ON DELETE RESTRICT )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='参数版本条目表(append-only,按生效日期时点化取值)' COLLATE utf8mb4_general_ci; CREATE INDEX idx_param_values_batch_id ON param_values (batch_id); CREATE INDEX idx_param_values_effective_date ON param_values (effective_date); CREATE INDEX idx_param_values_param_id_dimension_value_effective_date ON param_values (param_id, dimension_value, effective_date); -- --------------------------------------------------------------------------- -- 营销人员表(V4 迁移;T+ 同步不覆盖岗位与工资标准) -- --------------------------------------------------------------------------- CREATE TABLE personnel ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, personnel_name VARCHAR(64) NOT NULL COMMENT '姓名', business_role_id BIGINT UNSIGNED NOT NULL COMMENT '岗位角色ID(决定计提公式模板;T+同步不覆盖)', manager_id BIGINT UNSIGNED COMMENT '直属营销经理ID(NULL=经理本人或未分配;团队成员关系锚点)', phone VARCHAR(20) COMMENT '联系电话', hire_date DATE COMMENT '入职日期', is_probation TINYINT NOT NULL COMMENT '是否试用期:1是 0否(试用期绩效照算不发放)' DEFAULT '0', salary_standard DECIMAL(12, 2) COMMENT '月工资标准(元;T+同步不覆盖)', status TINYINT NOT NULL COMMENT '状态:1在职 0离职(离职人员不可再被业务/客户归属引用)' DEFAULT '1', remark VARCHAR(255) COMMENT '备注', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, source_no VARCHAR(64) COMMENT 'T+ 原始单据号(同步幂等去重锚点;唯一键待 IT 定键后升级)', t_plus_id VARCHAR(64) COMMENT 'T+ 系统内部标识', sync_batch_no VARCHAR(32) COMMENT '同步批次号(同步模块写入)', synced_at DATETIME COMMENT '最近同步时间', CONSTRAINT pk_personnel PRIMARY KEY (id), CONSTRAINT fk_personnel_business_role_id FOREIGN KEY(business_role_id) REFERENCES business_roles (id) ON DELETE RESTRICT, CONSTRAINT fk_personnel_manager_id FOREIGN KEY(manager_id) REFERENCES personnel (id) ON DELETE RESTRICT )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='营销人员表(T+同步不覆盖岗位与工资标准)' COLLATE utf8mb4_general_ci; CREATE INDEX idx_personnel_business_role_id ON personnel (business_role_id); CREATE INDEX idx_personnel_manager_id ON personnel (manager_id); CREATE INDEX idx_personnel_source_no ON personnel (source_no); -- --------------------------------------------------------------------------- -- 产品辐射区域表(V4 迁移) -- --------------------------------------------------------------------------- CREATE TABLE personnel_regions ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, personnel_id BIGINT UNSIGNED NOT NULL COMMENT '人员ID(personnel.id)', region_name VARCHAR(128) NOT NULL COMMENT '区域名称(产品辐射地理范围)', remark VARCHAR(255) COMMENT '备注', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_personnel_regions PRIMARY KEY (id), CONSTRAINT fk_personnel_regions_personnel_id FOREIGN KEY(personnel_id) REFERENCES personnel (id) ON DELETE RESTRICT )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='产品辐射区域表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_personnel_regions_personnel_id ON personnel_regions (personnel_id); -- --------------------------------------------------------------------------- -- 市场拓展计划表(V4 迁移) -- --------------------------------------------------------------------------- CREATE TABLE personnel_plans ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, personnel_id BIGINT UNSIGNED NOT NULL COMMENT '人员ID(personnel.id)', plan_period VARCHAR(32) NOT NULL COMMENT '计划期间(如 2026Q1、2026-05)', plan_content VARCHAR(500) NOT NULL COMMENT '计划内容', target_desc VARCHAR(255) COMMENT '指标说明(文字描述)', source_no VARCHAR(64) COMMENT 'T+ 原始条目号(预留)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_personnel_plans PRIMARY KEY (id), CONSTRAINT fk_personnel_plans_personnel_id FOREIGN KEY(personnel_id) REFERENCES personnel (id) ON DELETE RESTRICT )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='市场拓展计划表' COLLATE utf8mb4_general_ci; CREATE INDEX idx_personnel_plans_personnel_id ON personnel_plans (personnel_id); -- --------------------------------------------------------------------------- -- 产品表(V4 迁移;类别锚定折算阈值参数,T+ 同步不覆盖产品类别) -- --------------------------------------------------------------------------- CREATE TABLE products ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, product_name VARCHAR(128) NOT NULL COMMENT '产品名称', spec_model VARCHAR(128) NOT NULL COMMENT '规格型号(空串而非 NULL:参与组合唯一键,MySQL 组合索引对 NULL 不去重)' DEFAULT '', unit VARCHAR(16) COMMENT '计量单位', stock_quantity DECIMAL(14, 2) COMMENT '数量(T+ 同步原样存储,语义待 IT 确认)', sale_price DECIMAL(14, 4) COMMENT '销售单价(元,T+ 同步)', product_category VARCHAR(32) NOT NULL COMMENT '产品类别:municipal_water市政水利 rail_transit轨道交通(决定折算阈值 30%/20%;T+同步不覆盖)', status TINYINT NOT NULL COMMENT '状态:1启用 0停用' DEFAULT '1', remark VARCHAR(255) COMMENT '备注', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, source_no VARCHAR(64) COMMENT 'T+ 原始单据号(同步幂等去重锚点;唯一键待 IT 定键后升级)', t_plus_id VARCHAR(64) COMMENT 'T+ 系统内部标识', sync_batch_no VARCHAR(32) COMMENT '同步批次号(同步模块写入)', synced_at DATETIME COMMENT '最近同步时间', CONSTRAINT pk_products PRIMARY KEY (id), CONSTRAINT uk_products_name_spec UNIQUE (product_name, spec_model) )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='产品表(类别锚定折算阈值参数;T+同步不覆盖产品类别)' COLLATE utf8mb4_general_ci; CREATE INDEX idx_products_source_no ON products (source_no); -- --------------------------------------------------------------------------- -- 客户表(V4 迁移;公司名称+负责人为业务唯一标识,T+ 同步不覆盖客户分类) -- --------------------------------------------------------------------------- CREATE TABLE customers ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, company_name VARCHAR(128) NOT NULL COMMENT '公司名称', owner_name VARCHAR(64) NOT NULL COMMENT '客户负责人姓名(客户公司负责人的人名,非系统人员)', contact_person VARCHAR(64) COMMENT '联系人', contact_phone VARCHAR(20) COMMENT '联系电话', address VARCHAR(255) COMMENT '地址', industry VARCHAR(64) COMMENT '所属行业(自由文本)', customer_type VARCHAR(32) NOT NULL COMMENT '客户分类:personal个人户 manager_personal经理个人户 enterprise企业户(计提规则匹配锚点;T+同步不覆盖)' DEFAULT 'personal', owner_personnel_id BIGINT UNSIGNED COMMENT '归属负责营销人员ID(手动修改不回溯历史,变更留痕见 ownership_change_logs)', remark VARCHAR(255) COMMENT '备注', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL COMMENT '更新时间' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, source_no VARCHAR(64) COMMENT 'T+ 原始单据号(同步幂等去重锚点;唯一键待 IT 定键后升级)', t_plus_id VARCHAR(64) COMMENT 'T+ 系统内部标识', sync_batch_no VARCHAR(32) COMMENT '同步批次号(同步模块写入)', synced_at DATETIME COMMENT '最近同步时间', CONSTRAINT pk_customers PRIMARY KEY (id), CONSTRAINT uk_customers_company_owner UNIQUE (company_name, owner_name), CONSTRAINT fk_customers_owner_personnel_id FOREIGN KEY(owner_personnel_id) REFERENCES personnel (id) ON DELETE RESTRICT )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='客户表(公司名称+负责人为业务唯一标识;T+同步不覆盖客户分类)' COLLATE utf8mb4_general_ci; CREATE INDEX idx_customers_customer_type ON customers (customer_type); CREATE INDEX idx_customers_owner_personnel_id ON customers (owner_personnel_id); CREATE INDEX idx_customers_source_no ON customers (source_no); -- --------------------------------------------------------------------------- -- 归属变更记录表(V4 迁移,append-only;客户/业务归属变更留痕,不回溯历史) -- --------------------------------------------------------------------------- CREATE TABLE ownership_change_logs ( id BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, owner_type TINYINT NOT NULL COMMENT '归属类型:1客户归属 2业务归属', customer_id BIGINT UNSIGNED COMMENT '客户ID(固化,owner_type=1 时非空)', business_id BIGINT UNSIGNED COMMENT '业务ID(固化,owner_type=2 时非空)', old_owner_personnel_id BIGINT UNSIGNED COMMENT '变更前负责营销人员ID(固化)', new_owner_personnel_id BIGINT UNSIGNED COMMENT '变更后负责营销人员ID(固化)', old_assistant_personnel_id BIGINT UNSIGNED COMMENT '变更前协助营销人员ID(固化,仅业务归属使用)', new_assistant_personnel_id BIGINT UNSIGNED COMMENT '变更后协助营销人员ID(固化,仅业务归属使用)', change_reason VARCHAR(255) COMMENT '变更原因', operator_id BIGINT UNSIGNED COMMENT '操作人ID(账号删除后置空)', operator_name VARCHAR(64) NOT NULL COMMENT '操作人用户名(冗余固化)', create_time DATETIME NOT NULL COMMENT '创建时间' DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_ownership_change_logs PRIMARY KEY (id), CONSTRAINT fk_ownership_change_logs_operator_id FOREIGN KEY(operator_id) REFERENCES users (id) ON DELETE SET NULL )CHARSET=utf8mb4 ENGINE=InnoDB COMMENT='归属变更记录表(append-only;客户/业务归属变更留痕,不回溯历史)' COLLATE utf8mb4_general_ci; CREATE INDEX idx_ownership_change_logs_customer_id ON ownership_change_logs (customer_id); CREATE INDEX idx_ownership_change_logs_business_id ON ownership_change_logs (business_id); CREATE INDEX idx_ownership_change_logs_create_time ON ownership_change_logs (create_time); -- --------------------------------------------------------------------------- -- 字典数据:角色(与 V1 迁移中的初始化数据一致) -- --------------------------------------------------------------------------- INSERT INTO roles (role_code, role_name, description, sort_order) VALUES ('admin', '系统管理员', '全部权限,含计提参数与系数表配置', 1); INSERT INTO roles (role_code, role_name, description, sort_order) VALUES ('user', '普通用户', '业务操作', 2); -- --------------------------------------------------------------------------- -- 字典数据:业务岗位与计提参数(与 V3 迁移种子一致;口径依据 2026-10-12 业务裁决) -- 显式指定 id:param_values 按 param_id 引用定义,与迁移种子保持同源一致 -- --------------------------------------------------------------------------- INSERT INTO business_roles (id, role_code, role_name, calc_template, description, sort_order, is_builtin) VALUES (1, 'salesperson', '营销员', 'TPL_SALESPERSON_DECAY', '业务员个人户:回款天数线性递减(10‰ − 天数×4/360‰,361 天起固定 4‰)', 1, 1), (2, 'sales_manager', '营销经理', 'TPL_MANAGER_SHARE', '经理绩效:∑本团队业务员绩效×12.5% + ∑全公司业务员绩效×5%', 2, 1), (3, 'info_officer', '信息员', 'TPL_INFO_SALES_FIXED', '信息员绩效:本人销售额×1‰', 3, 1); INSERT INTO param_change_batches (id, version_no, effective_date, change_type, remark, operator_name, item_count) VALUES (1, 'P20260101-00', '2026-01-01', 1, '初始版本(系统初始化种子,口径依据 2026-10-12 业务裁决)', 'system', 19); INSERT INTO param_definitions (id, param_code, param_name, param_group, value_type, unit, dimension_type, options_text, default_value, value_min, value_max, description, sort_order) VALUES (1, 'salesperson.rate.start', '业务员起始计提比例', '业务员个人户', 'DECIMAL', '‰', 'BUSINESS_ROLE', NULL, '10', '0', NULL, '线性递减段起始值:比例 = 起始 − 回款天数 × 斜率(≤分界天数)', 1), (2, 'salesperson.rate.slope', '业务员日递减斜率', '业务员个人户', 'DECIMAL', '‰/天', 'BUSINESS_ROLE', NULL, '4/360', '0', NULL, '精确分数 4/360‰/天(=1/90),禁止按 0.011111 截断存储', 2), (3, 'salesperson.rate.floor', '业务员计提下限', '业务员个人户', 'DECIMAL', '‰', 'BUSINESS_ROLE', NULL, '4', '0', NULL, '回款天数超过分界天数后固定取此比例(≥361 天 = 4‰)', 3), (4, 'salesperson.days.boundary', '线性递减分界天数', '业务员个人户', 'INT', '天', 'BUSINESS_ROLE', NULL, '360', '0', NULL, '≤分界天数按公式线性递减(360 天=6‰);超过则取下限', 4), (5, 'manager.share.team', '经理本团队分成比例', '经理分成', 'DECIMAL', '%', 'BUSINESS_ROLE', NULL, '12.5', '0', '100', '∑本人带领业务员绩效 × 此比例(限本团队)', 5), (6, 'manager.share.company', '经理全公司分成比例', '经理分成', 'DECIMAL', '%', 'BUSINESS_ROLE', NULL, '5', '0', '100', '∑全部业务员绩效 × 此比例(全公司)', 6), (7, 'enterprise.rate', '企业户计提比例', '企业户', 'DECIMAL', '‰', 'PRODUCT_CATEGORY', NULL, '3', '0', NULL, '所有企业户适用;2026-08-13 起由 2‰ 提高至 3‰', 7), (8, 'info.rate', '信息员计提比例', '信息员', 'DECIMAL', '‰', 'BUSINESS_ROLE', NULL, '1', '0', NULL, '信息员绩效 = 本人销售额 × 此比例', 8), (9, 'prepay.rate', '预付款计提比例', '支付环节', 'DECIMAL', '‰', 'NONE', NULL, '10', '0', NULL, '预付款统一按此比例计提', 9), (10, 'barter.discount', '以物抵顶折算比例', '支付环节', 'DECIMAL', '%', 'NONE', NULL, '80', '0', '100', '以物抵顶回款绩效按应发绩效的此比例折算', 10), (11, 'payment.start.ratio', '支付起付比例', '支付环节', 'DECIMAL', '%', 'NONE', NULL, '60', '0', '100', '单项业务回款额达销售额(不含运费)此比例后起付;达标前累计', 11), (12, 'payment.weight.mode', '支付权重应用方式', '支付环节', 'ENUM', NULL, 'NONE', 'FULL|BALANCE', 'FULL', NULL, NULL, 'FULL=按 R×R 乘当月全额应发绩效;BALANCE=乘余额(语义待 M3 前确认)', 12), (13, 'product.threshold', '折算毛利润额阈值', '产品阈值', 'DECIMAL', '%', 'PRODUCT_CATEGORY', NULL, '30', '0', '100', '折算毛利润额 = 销售额 ×(毛利润率 − 阈值);市政水利 30%、轨交 20%', 13), (14, 'salary.basic.mode', '月工资基本工资口径', '月工资口径', 'ENUM', NULL, 'BUSINESS_ROLE', 'INCLUDE|DEDUCT|EXCLUDE', 'INCLUDE', NULL, NULL, 'INCLUDE含基本工资 / DEDUCT扣除基本工资 / EXCLUDE不计', 14), (15, 'probation.annual.threshold', '试用期年累计结算阈值', '月工资口径', 'DECIMAL', '元', 'NONE', NULL, '18000', '0', NULL, '试用期年累计绩效超过此值部分年底一次性结算', 15), (16, 'probation.salary.basic', '试用期基本工资标准', '月工资口径', 'DECIMAL', '元', 'NONE', NULL, '3000', '0', NULL, '试用期仅发基本工资、不发放绩效(归属待 M2 复核)', 16); INSERT INTO param_values (id, param_id, dimension_value, effective_date, value_text, batch_id) VALUES (1, 1, 'salesperson', '2026-02-17', '10', 1), (2, 2, 'salesperson', '2026-02-17', '4/360', 1), (3, 3, 'salesperson', '2026-02-17', '4', 1), (4, 4, 'salesperson', '2026-02-17', '360', 1), (5, 5, 'sales_manager', '2026-08-13', '12.5', 1), (6, 6, 'sales_manager', '2026-08-13', '5', 1), (7, 7, '', '2026-02-17', '2', 1), (8, 7, '', '2026-08-13', '3', 1), (9, 8, 'info_officer', '2026-08-13', '1', 1), (10, 9, '', '2026-01-01', '10', 1), (11, 10, '', '2026-01-01', '80', 1), (12, 11, '', '2026-01-01', '60', 1), (13, 12, '', '2026-01-01', 'FULL', 1), (14, 13, 'municipal_water', '2026-02-17', '30', 1), (15, 13, 'rail_transit', '2026-02-17', '20', 1), (16, 14, 'salesperson', '2026-01-01', 'INCLUDE', 1), (17, 14, 'sales_manager', '2026-01-01', 'DEDUCT', 1), (18, 15, '', '2026-01-01', '18000', 1), (19, 16, '', '2026-01-01', '3000', 1); -- --------------------------------------------------------------------------- -- 迁移版本记录:须等于当前 head,使 alembic upgrade head 成为空操作 -- --------------------------------------------------------------------------- CREATE TABLE alembic_version ( version_num VARCHAR(32) NOT NULL, CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num) )CHARSET=utf8mb4 ENGINE=InnoDB COLLATE utf8mb4_general_ci; INSERT INTO alembic_version (version_num) VALUES ('e1133a7c670a');