代理分润系统是源码交易平台、转卡码平台、支付中转服务等商业系统的核心功能模块之一。一套设计合理的分润数据库,不仅能准确记录每一笔分润流水,还能支撑高并发结算、多级代理关系和灵活的规则配置。

本文将从实战角度出发,完整讲解代理分润系统的数据库设计思路与核心SQL实现,涵盖代理等级管理、分润规则配置、自动结算与提现审批的全流程。文中所有建表语句和代码示例均来自 源码商城 实际使用的转卡码系统。

一、核心业务模型与ER设计

代理分润系统涉及五个核心实体:代理用户代理等级分润规则结算流水提现申请。它们之间的核心关系如下:

  • 一个代理属于一个等级(等级定义了分润百分比和提现门槛)
  • 每个等级可以配置多条分润规则(按订单类型、商品分类区分)
  • 每笔成功订单生成一条或多条结算流水(关联到具体代理和规则)
  • 代理发起提现,关联多条已结算流水

二、核心建表语句

1. 代理等级表(agent_levels)

CREATE TABLE `agent_levels` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '等级名称,如 普通代理、高级代理、金牌代理',
  `level` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '等级数值,越大权限越高',
  `profit_percent` decimal(5,2) NOT NULL DEFAULT 0.00 COMMENT '默认分润百分比,如 30.00 表示 30%',
  `min_withdraw` decimal(10,2) NOT NULL DEFAULT 100.00 COMMENT '最低提现金额(元)',
  `max_withdraw_daily` decimal(10,2) NOT NULL DEFAULT 5000.00 COMMENT '每日提现上限',
  `auto_settle` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否自动结算 1=是 0=否',
  `settle_interval` varchar(20) NOT NULL DEFAULT 'daily' COMMENT '结算周期:daily/weekly/monthly',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_level` (`level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代理等级表';

2. 代理用户表(agents)

CREATE TABLE `agents` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) unsigned NOT NULL COMMENT '关联user表',
  `parent_agent_id` int(11) unsigned DEFAULT NULL COMMENT '上级代理ID,NULL表示顶级',
  `level_id` int(11) unsigned NOT NULL COMMENT '当前代理等级ID',
  `invite_code` varchar(32) NOT NULL COMMENT '唯一邀请码',
  `total_earnings` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT '累计收益',
  `balance` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT '可提现余额',
  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '1=正常 0=冻结',
  `applied_at` datetime DEFAULT NULL COMMENT '申请成为代理的时间',
  `approved_at` datetime DEFAULT NULL COMMENT '审核通过时间',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_invite_code` (`invite_code`),
  UNIQUE KEY `uk_user_id` (`user_id`),
  KEY `idx_parent` (`parent_agent_id`),
  KEY `idx_level` (`level_id`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代理用户表';

3. 分润规则表(profit_rules)

CREATE TABLE `profit_rules` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `level_id` int(11) unsigned NOT NULL COMMENT '关联代理等级',
  `rule_name` varchar(100) NOT NULL COMMENT '规则名称',
  `product_type` varchar(50) DEFAULT NULL COMMENT '商品类型,NULL表示全部',
  `profit_type` enum('percent','fixed') NOT NULL DEFAULT 'percent' COMMENT '分润类型:百分比或固定金额',
  `profit_value` decimal(10,2) NOT NULL COMMENT '分润值(百分比如30.00 或 固定金额如5.00)',
  `parent_share` decimal(5,2) DEFAULT 0.00 COMMENT '上级代理分润比例(%),支持多级',
  `grandparent_share` decimal(5,2) DEFAULT 0.00 COMMENT '上上级代理分润比例',
  `priority` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT '优先级,数值越大越优先',
  `status` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_level_product` (`level_id`, `product_type`),
  KEY `idx_priority` (`priority`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分润规则表';

4. 结算流水表(settlement_logs)

这是整个系统最核心的表,每笔订单的每一级分润都会生成一条记录:

CREATE TABLE `settlement_logs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` varchar(64) NOT NULL COMMENT '原始订单ID',
  `agent_id` int(11) unsigned NOT NULL COMMENT '获得分润的代理ID',
  `profit_rule_id` int(11) unsigned DEFAULT NULL COMMENT '关联的分润规则ID',
  `order_amount` decimal(10,2) NOT NULL COMMENT '订单金额',
  `profit_amount` decimal(10,2) NOT NULL COMMENT '分润金额',
  `profit_level` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '分润层级:1=直推 2=间推 3=三级',
  `status` enum('pending','settled','frozen','cancelled') NOT NULL DEFAULT 'pending' COMMENT '结算状态',
  `settle_batch_no` varchar(64) DEFAULT NULL COMMENT '结算批次号,用于批量结算对账',
  `remark` varchar(255) DEFAULT NULL,
  `settled_at` datetime DEFAULT NULL COMMENT '实际结算时间',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_order_id` (`order_id`),
  KEY `idx_agent_id` (`agent_id`),
  KEY `idx_status` (`status`),
  KEY `idx_agent_status` (`agent_id`, `status`),
  KEY `idx_settle_batch` (`settle_batch_no`),
  KEY `idx_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='结算流水表';

-- 按月分区示例,提升海量数据查询性能
ALTER TABLE `settlement_logs`
PARTITION BY RANGE (TO_DAYS(`created_at`)) (
  PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
  PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')),
  PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')),
  PARTITION p_future VALUES LESS THAN MAXVALUE
);

5. 提现申请表(withdraw_requests)

CREATE TABLE `withdraw_requests` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `agent_id` int(11) unsigned NOT NULL,
  `amount` decimal(10,2) NOT NULL COMMENT '提现金额',
  `fee` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '手续费',
  `actual_amount` decimal(10,2) NOT NULL COMMENT '实际到账金额',
  `account_type` enum('alipay','wechat','bank') NOT NULL COMMENT '提现账户类型',
  `account_info` varchar(500) NOT NULL COMMENT '账户信息JSON',
  `status` enum('pending','processing','success','failed','rejected') NOT NULL DEFAULT 'pending',
  `reviewer_id` int(11) unsigned DEFAULT NULL COMMENT '审核人',
  `review_remark` varchar(255) DEFAULT NULL,
  `reviewed_at` datetime DEFAULT NULL,
  `completed_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_agent_id` (`agent_id`),
  KEY `idx_status` (`status`),
  KEY `idx_agent_status` (`agent_id`, `status`),
  KEY `idx_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提现申请表';

三、分润计算逻辑的Python实现

有了数据库表结构,接下来看看分润计算的完整逻辑。以下是一个通用的多级分润计算函数:

#!/usr/bin/env python3
# profit_calc.py - 多级分润计算引擎

import pymysql
from decimal import Decimal

def calculate_profit(order_id, order_amount, product_type):
    """
    根据订单计算各级代理分润
    返回分润记录列表 [(agent_id, profit_amount, level), ...]
    """
    conn = get_db_connection()
    cursor = conn.cursor(pymysql.cursors.DictCursor)

    # 1. 查询下单用户的上级代理链(最多3级)
    cursor.execute("""
        WITH RECURSIVE agent_chain AS (
            SELECT id, user_id, parent_agent_id, level_id, 1 AS depth
            FROM agents WHERE user_id = %s
            UNION ALL
            SELECT a.id, a.user_id, a.parent_agent_id, a.level_id, ac.depth + 1
            FROM agents a
            INNER JOIN agent_chain ac ON a.id = ac.parent_agent_id
            WHERE ac.depth < 3
        )
        SELECT * FROM agent_chain ORDER BY depth
    """, (order_user_id,))
    chain = cursor.fetchall()

    # 2. 对每一级代理,查询匹配的分润规则
    profit_records = []
    for row in chain:
        agent_id = row['id']
        level_id = row['level_id']
        depth = row['depth']

        cursor.execute("""
            SELECT * FROM profit_rules
            WHERE level_id = %s
              AND (product_type IS NULL OR product_type = %s)
              AND status = 1
            ORDER BY priority DESC
            LIMIT 1
        """, (level_id, product_type))
        rule = cursor.fetchone()
        if not rule:
            continue

        # 根据规则计算分润金额
        share_key = {1: 'parent_share', 2: 'grandparent_share'}.get(depth)
        if depth == 1:
            profit_pct = Decimal(str(rule['profit_value']))
        elif share_key and rule[share_key]:
            profit_pct = Decimal(str(rule[share_key]))
        else:
            continue

        profit_amount = order_amount * profit_pct / Decimal('100')
        profit_records.append({
            'agent_id': agent_id,
            'order_id': order_id,
            'order_amount': order_amount,
            'profit_amount': profit_amount.quantize(Decimal('0.01')),
            'profit_level': depth,
            'profit_rule_id': rule['id'],
            'status': 'pending'
        })

    # 3. 批量插入结算流水表
    if profit_records:
        insert_sql = """
            INSERT INTO settlement_logs
            (order_id, agent_id, profit_rule_id, order_amount,
             profit_amount, profit_level, status)
            VALUES (%(order_id)s, %(agent_id)s, %(profit_rule_id)s,
                    %(order_amount)s, %(profit_amount)s, %(profit_level)s, %(status)s)
        """
        cursor.executemany(insert_sql, profit_records)
        conn.commit()

    cursor.close()
    conn.close()
    return profit_records

四、索引优化与性能调优

分润系统在日订单量过万后,结算流水表会迅速膨胀到百万级。以下是我在实际项目中总结的关键优化策略:

4.1 复合索引优先

最频繁的查询是按代理ID+状态筛选待结算记录:

-- 高频查询:查某个代理的待结算流水
EXPLAIN SELECT * FROM settlement_logs WHERE agent_id=123 AND status='pending';
-- 已经建立了复合索引 idx_agent_status,覆盖此查询

-- 查某批次的结算记录用于对账
EXPLAIN SELECT * FROM settlement_logs WHERE settle_batch_no='B20260713001';
-- idx_settle_batch 索引确保该查询走索引而非全表扫描

4.2 按月分区表

如前文建表语句所示,对 settlement_logs 按月分区后,查询某个月的数据直接在对应分区扫描,避免跨分区全表扫描。配合定时任务自动创建新分区:

# crontab - 每月1日凌晨创建下月分区
0 3 1 * * /usr/bin/python3 /opt/scripts/create_partition.py

4.3 批量结算代替逐条结算

不要在每次订单完成时立即结算,而是使用定时任务批量结算,减少数据库事务频次:

UPDATE settlement_logs
SET status = 'settled',
    settle_batch_no = CONCAT('B', DATE_FORMAT(NOW(), '%Y%m%d'), LPAD(@batch_seq, 4, '0')),
    settled_at = NOW()
WHERE status = 'pending'
  AND created_at < DATE_SUB(NOW(), INTERVAL 1 HOUR)
LIMIT 500;

五、与转卡码系统的集成

源码商城 提供的 转卡码系统 中,代理分润模块与订单系统深度集成。当客户购买卡密并通过回调确认支付成功后,系统自动根据上述数据库结构和计算逻辑,在同一个事务中完成以下操作:

  1. 扣减卡密库存
  2. 记录订单状态为已支付
  3. 查询下单用户的代理链
  4. 按照分润规则表计算各级分润
  5. 插入结算流水记录
  6. 更新代理余额

💡 提示: 源码商城的转卡码系统 V3 版本内置了完整的代理分润模块,支持多级代理、自动结算、批量提现等功能。购买即送完整数据库设计文档。

六、总结

一个设计良好的代理分润数据库,是整个代理体系稳定运行的基石。本文从五个核心表出发,完整介绍了代理分润系统的数据库设计思路、SQL建表语句、Python分润计算实现以及索引优化策略。良好的ER设计加上合理的索引和分区,可以支撑百万级日订单量的分润结算需求。

关键设计要点回顾:

  • 结算流水表 采用按月分区,配合复合索引覆盖高频查询
  • 分润规则表 支持百分比与固定金额两种模式,并可配置多级代理共享比例
  • 批量结算 代替逐条更新,显著降低数据库压力
  • 使用 递归CTE 高效查询代理链,避免应用层多次查询