PayrollManagementSystem/db/init/init-dev.sql
liuwenxin f22d14e439 feat(base): 新增基础数据六表及 V4 迁移(人员/辐射区域/拓展计划/产品/客户/归属留痕)
- TPlusSyncMixin 统一 T+ 同步预留四列(可空+普通索引,唯一键待 IT 定键后升级)
- 留痕表实体 ID 无外键冗余固化,删除保护由服务层承担
- init-dev.sql 同步六表 DDL,alembic_version 标记更新

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 09:49:05 +08:00

471 lines
33 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ============================================================================
-- 开发环境初始化脚本
--
-- 执行时机: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');