# IoT SIM 管理系统 - 分佣系统说明 ## 概述 IoT SIM 管理系统实现了一套灵活的多级代理分佣体系,支持三种分佣模式(一次性分佣、长期分佣、组合分佣),支持阶梯奖励机制,支持自动解冻和手动审批,支持 OR 条件解冻逻辑。 --- ## 分佣架构 ### 多级代理树形结构 ``` ┌─────────────────────────────────────────────────────────┐ │ 平台(Platform) │ │ Level 0 │ └─────────────────────────────────────────────────────────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 一级代理 A │ │ 一级代理 B │ │ 一级代理 C │ │ Level 1 │ │ Level 1 │ │ Level 1 │ │ Path: /A/ │ │ Path: /B/ │ │ Path: /C/ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ├────┬────┐ ├────┬────┐ ▼ ▼ ▼ ▼ ▼ ▼ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │A-1 │ │A-2 │ │A-3 │ │B-1 │ │B-2 │ │B-3 │ │L2 │ │L2 │ │L2 │ │L2 │ │L2 │ │L2 │ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ ``` **代理层级关系表**: `agent_hierarchies` --- ## 三种分佣模式 ### 1. 一次性分佣 (One-time Commission) **特点**: 订单完成后立即发放佣金 **适用场景**: - 首次激活奖励 - 推广奖励 - 快速返佣 **示例**: ``` 用户购买套餐 → 订单完成 → 立即发放佣金给上级代理 ``` **配置示例**: ```sql INSERT INTO commission_rules ( rule_name, rule_type, package_series_id, commission_type, commission_value, status ) VALUES ( '一次性分佣-套餐激活奖励', 'one_time', 1, -- 套餐系列 ID 'fixed', -- 固定金额 10.00, -- 10元 1 -- 启用 ); ``` **业务流程**: ``` 订单创建 → 订单支付 → 订单完成 │ └─→ 创建分佣记录 (status=1 待发放) │ └─→ 自动发放 (status=2 已发放) ``` --- ### 2. 长期分佣 (Long-term Commission) **特点**: 订单完成后冻结佣金,满足解冻条件后发放 **适用场景**: - 续费奖励 - 留存奖励 - 长期激励 **解冻条件**: - **时间条件**: 冻结 N 天后自动解冻 - **流量条件**: IoT 卡累计使用 M MB 流量后解冻 - **OR 逻辑**: 时间到期 **OR** 流量达标,满足任一条件即可解冻 **示例**: ``` 用户购买套餐 → 订单完成 → 冻结佣金 (30天或1GB流量) ↓ 时间到期 OR 流量达标 ↓ 自动解冻发放 ``` **配置示例**: ```sql INSERT INTO commission_rules ( rule_name, rule_type, package_series_id, commission_type, commission_value, freeze_days, freeze_data_mb, unfreeze_mode, status ) VALUES ( '长期分佣-续费奖励', 'long_term', 1, 'percentage', -- 百分比 0.10, -- 10% 30, -- 冻结30天 1024, -- 或使用1GB流量 'auto', -- 自动解冻 1 ); ``` **业务流程**: ``` 订单创建 → 订单支付 → 订单完成 │ └─→ 创建分佣记录 (status=3 已冻结) │ ├─→ 时间检查: 30天后 → 自动解冻 (status=2 已发放) │ └─→ 流量检查: 使用1GB流量后 → 自动解冻 (status=2 已发放) ``` **解冻条件数据结构**: ```json { "time_based": { "days": 30, "deadline": "2025-02-10T00:00:00Z" }, "data_based": { "data_mb": 1024, "iot_card_id": 12345 } } ``` --- ### 3. 组合分佣 (Combined Commission) **特点**: 同时包含一次性分佣和长期分佣,订单完成后部分立即发放,部分冻结 **适用场景**: - 首充奖励(立即发放) + 留存奖励(冻结发放) - 灵活激励机制 **示例**: ``` 用户购买套餐 → 订单完成 → 立即发放 5元 + 冻结 10元 (30天后发放) ``` **配置示例**: ```sql -- 1. 创建组合分佣规则 INSERT INTO commission_rules ( rule_name, rule_type, package_series_id, status ) VALUES ( '组合分佣-首充+留存', 'combined', 1, 1 ); -- 2. 配置一次性条件 INSERT INTO commission_combined_conditions ( rule_id, condition_type, commission_type, commission_value ) VALUES ( 1, -- 上面创建的规则 ID 'one_time', 'fixed', 5.00 -- 立即发放 5元 ); -- 3. 配置长期条件 INSERT INTO commission_combined_conditions ( rule_id, condition_type, commission_type, commission_value, freeze_days, freeze_data_mb ) VALUES ( 1, 'long_term', 'fixed', 10.00, -- 冻结 10元 30, -- 30天 1024 -- 或1GB流量 ); ``` **业务流程**: ``` 订单创建 → 订单支付 → 订单完成 │ ├─→ 创建一次性分佣记录 (status=1 待发放) → 立即发放 (status=2) │ └─→ 创建长期分佣记录 (status=3 已冻结) → 满足条件后解冻 ``` --- ## 阶梯奖励机制 ### 阶梯奖励说明 阶梯奖励允许根据订单数量设置不同的分佣标准,订单数量越多,分佣越高。 **示例配置**: ``` 1-10 单: 10元/单 11-50 单: 15元/单 51+ 单: 20元/单 ``` ### 配置示例 ```sql -- 1. 创建支持阶梯的分佣规则 INSERT INTO commission_rules ( rule_name, rule_type, package_series_id, enable_ladder, status ) VALUES ( '阶梯分佣-月度订单量', 'one_time', 1, true, -- 启用阶梯 1 ); -- 2. 配置阶梯奖励 INSERT INTO commission_ladder (rule_id, min_quantity, max_quantity, commission_type, commission_value) VALUES (1, 1, 10, 'fixed', 10.00), (1, 11, 50, 'fixed', 15.00), (1, 51, NULL, 'fixed', 20.00); -- NULL 表示无上限 ``` ### 阶梯计算逻辑 ```go // 伪代码 func CalculateLadderCommission(agentID uint, ruleID uint, currentMonth string) float64 { // 1. 查询阶梯配置 ladders := db.FindCommissionLadders(ruleID) // 2. 统计当月订单数量 orderCount := db.CountOrders(agentID, currentMonth) // 3. 匹配阶梯 for _, ladder := range ladders { if orderCount >= ladder.MinQuantity && (ladder.MaxQuantity == nil || orderCount <= ladder.MaxQuantity) { if ladder.CommissionType == "fixed" { return ladder.CommissionValue } else if ladder.CommissionType == "percentage" { orderAmount := db.GetOrderAmount(orderID) return orderAmount * ladder.CommissionValue } } } return 0 } ``` --- ## 分佣计算方式 ### 1. 固定金额 (Fixed) **说明**: 每笔订单固定分佣 N 元 **示例**: ```sql commission_type = 'fixed' commission_value = 10.00 ``` **计算公式**: ``` 分佣金额 = commission_value = 10.00 元 ``` --- ### 2. 百分比 (Percentage) **说明**: 按订单金额的 N% 分佣 **示例**: ```sql commission_type = 'percentage' commission_value = 0.10 -- 10% ``` **计算公式**: ``` 分佣金额 = 订单金额 × commission_value = 100.00 × 0.10 = 10.00 元 ``` --- ## 分佣记录表 ### 表结构: `commission_records` 分佣记录表记录每笔分佣的详细信息: ```sql CREATE TABLE commission_records ( id BIGSERIAL PRIMARY KEY, order_id BIGINT NOT NULL, agent_id BIGINT NOT NULL, rule_id BIGINT NOT NULL, commission_type VARCHAR(50) NOT NULL, commission_amount DECIMAL(10,2) NOT NULL, status INT NOT NULL DEFAULT 1, freeze_days INT DEFAULT 0, freeze_data_mb BIGINT DEFAULT 0, unfreeze_conditions JSONB, unfrozen_at TIMESTAMPTZ, distributed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 状态说明 | status | 状态 | 说明 | |--------|------|------| | 1 | 待发放 | 一次性分佣,等待发放 | | 2 | 已发放 | 已发放到代理账户 | | 3 | 已冻结 | 长期分佣,冻结中 | | 4 | 已取消 | 订单取消或退款,分佣取消 | --- ## OR 条件解冻逻辑 ### 解冻条件设计 长期分佣支持 **OR 条件解冻**,即时间到期 **OR** 流量达标,满足任一条件即可自动解冻。 **解冻条件数据结构**: ```json { "time_based": { "days": 30, "deadline": "2025-02-10T00:00:00Z" }, "data_based": { "data_mb": 1024, "iot_card_id": 12345 } } ``` ### 解冻检查逻辑 ```go // 伪代码 func CheckUnfreezeConditions(record *CommissionRecord) bool { var conditions struct { TimeBased struct { Days int `json:"days"` Deadline time.Time `json:"deadline"` } `json:"time_based"` DataBased struct { DataMB int64 `json:"data_mb"` IotCardID uint `json:"iot_card_id"` } `json:"data_based"` } json.Unmarshal(record.UnfreezeConditions, &conditions) // 检查时间条件 if time.Now().After(conditions.TimeBased.Deadline) { return true // 时间到期,可以解冻 } // 检查流量条件 if conditions.DataBased.IotCardID > 0 { card := db.FindIotCardByID(conditions.DataBased.IotCardID) if card.DataUsageMB >= conditions.DataBased.DataMB { return true // 流量达标,可以解冻 } } return false // 条件均未满足 } ``` ### 自动解冻定时任务 ```go // 伪代码 func UnfreezeCommissionTask() { ticker := time.NewTicker(1 * time.Minute) defer ticker.Stop() for range ticker.C { // 查询所有冻结中的分佣记录 records := db.FindCommissionRecords("status = 3") for _, record := range records { if CheckUnfreezeConditions(&record) { // 解冻 record.Status = 2 // 已发放 record.UnfrozenAt = time.Now() record.DistributedAt = time.Now() db.Save(&record) // 发放到代理账户 DistributeCommission(record.AgentID, record.CommissionAmount) logger.Info("分佣解冻成功", zap.Uint("record_id", record.ID), zap.Uint("agent_id", record.AgentID), zap.Float64("amount", record.CommissionAmount), ) } } } } ``` --- ## 分佣审批流程 ### 自动审批 vs 手动审批 分佣规则的 `unfreeze_mode` 字段控制解冻模式: - **auto**: 自动解冻,满足条件后自动发放 - **manual**: 手动审批,需要人工审核通过后才能发放 ### 手动审批流程 ``` 订单完成 → 创建分佣记录 (status=3 已冻结) ↓ 满足解冻条件 ↓ 创建审批记录 (approval_status=1 待审批) ↓ 审批人审核 ├─→ 通过 (approval_status=2) → 发放佣金 (status=2 已发放) └─→ 拒绝 (approval_status=3) → 取消分佣 (status=4 已取消) ``` ### 审批表: `commission_approvals` ```sql CREATE TABLE commission_approvals ( id BIGSERIAL PRIMARY KEY, commission_record_id BIGINT UNIQUE NOT NULL, agent_id BIGINT NOT NULL, approval_status INT NOT NULL DEFAULT 1, approver_id BIGINT, approval_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 审批状态 | approval_status | 状态 | 说明 | |----------------|------|------| | 1 | 待审批 | 等待审批人审核 | | 2 | 已通过 | 审批通过,发放佣金 | | 3 | 已拒绝 | 审批拒绝,取消分佣 | --- ## 分佣模板 ### 模板设计 分佣模板用于快速创建分佣规则,避免重复配置。 **表结构**: `commission_templates` ```sql CREATE TABLE commission_templates ( id BIGSERIAL PRIMARY KEY, template_name VARCHAR(255) NOT NULL, template_data JSONB NOT NULL, description TEXT, status INT NOT NULL DEFAULT 1, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 模板数据格式 ```json { "rule_type": "combined", "package_series_id": 1, "conditions": [ { "condition_type": "one_time", "commission_type": "fixed", "commission_value": 5.00 }, { "condition_type": "long_term", "commission_type": "fixed", "commission_value": 10.00, "freeze_days": 30, "freeze_data_mb": 1024 } ] } ``` ### 使用模板创建规则 ```go // 伪代码 func CreateRuleFromTemplate(templateID uint, seriesID uint) error { template := db.FindTemplateByID(templateID) var data struct { RuleType string `json:"rule_type"` PackageSeriesID uint `json:"package_series_id"` Conditions []struct { ConditionType string `json:"condition_type"` CommissionType string `json:"commission_type"` CommissionValue float64 `json:"commission_value"` FreezeDays int `json:"freeze_days"` FreezeDataMB int64 `json:"freeze_data_mb"` } `json:"conditions"` } json.Unmarshal(template.TemplateData, &data) // 创建分佣规则 rule := CommissionRule{ RuleName: template.TemplateName, RuleType: data.RuleType, PackageSeriesID: seriesID, Status: 1, } db.Create(&rule) // 创建组合条件 for _, cond := range data.Conditions { condition := CommissionCombinedCondition{ RuleID: rule.ID, ConditionType: cond.ConditionType, CommissionType: cond.CommissionType, CommissionValue: cond.CommissionValue, FreezeDays: cond.FreezeDays, FreezeDataMB: cond.FreezeDataMB, } db.Create(&condition) } return nil } ``` --- ## 运营商结算 ### 结算表: `carrier_settlements` 记录与运营商的月度结算情况: ```sql CREATE TABLE carrier_settlements ( id BIGSERIAL PRIMARY KEY, carrier_id BIGINT NOT NULL, settlement_month VARCHAR(7) NOT NULL, total_orders INT DEFAULT 0, total_amount DECIMAL(10,2) DEFAULT 0, settlement_status INT NOT NULL DEFAULT 1, settled_at TIMESTAMPTZ, paid_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 结算状态 | settlement_status | 状态 | 说明 | |------------------|------|------| | 1 | 待结算 | 月度未结束 | | 2 | 已结算 | 已统计金额 | | 3 | 已支付 | 已支付给运营商 | ### 月度结算流程 ``` 每月1号 → 统计上月订单数据 ↓ 创建结算记录 (settlement_status=1 待结算) ↓ 财务审核 ↓ 确认结算 (settlement_status=2 已结算) ↓ 支付运营商 (settlement_status=3 已支付) ``` ### 结算计算逻辑 ```go // 伪代码 func GenerateCarrierSettlement(carrierID uint, month string) error { // 1. 统计上月订单 orders := db.FindOrders("carrier_id = ? AND DATE_FORMAT(completed_at, '%Y-%m') = ?", carrierID, month) totalOrders := len(orders) totalAmount := 0.0 for _, order := range orders { totalAmount += order.Amount } // 2. 创建结算记录 settlement := CarrierSettlement{ CarrierID: carrierID, SettlementMonth: month, TotalOrders: totalOrders, TotalAmount: totalAmount, SettlementStatus: 1, // 待结算 } db.Create(&settlement) return nil } ``` --- ## 提现管理 ### 提现申请表: `commission_withdrawal_requests` ```sql CREATE TABLE commission_withdrawal_requests ( id BIGSERIAL PRIMARY KEY, agent_id BIGINT NOT NULL, withdrawal_amount DECIMAL(10,2) NOT NULL, withdrawal_method VARCHAR(20) NOT NULL, account_info JSONB NOT NULL, status INT NOT NULL DEFAULT 1, reviewer_id BIGINT, review_reason TEXT, reviewed_at TIMESTAMPTZ, paid_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 提现状态 | status | 状态 | 说明 | |--------|------|------| | 1 | 待审核 | 等待审核 | | 2 | 已通过 | 审核通过,等待打款 | | 3 | 已拒绝 | 审核拒绝 | | 4 | 已打款 | 已打款到账户 | | 5 | 已取消 | 用户取消 | ### 提现流程 ``` 代理提交提现申请 (status=1 待审核) ↓ 财务审核 ├─→ 通过 (status=2 已通过) → 打款 (status=4 已打款) └─→ 拒绝 (status=3 已拒绝) ``` ### 提现设置表: `commission_withdrawal_settings` ```sql CREATE TABLE commission_withdrawal_settings ( id BIGSERIAL PRIMARY KEY, agent_id BIGINT UNIQUE NOT NULL, min_withdrawal_amount DECIMAL(10,2) DEFAULT 0, max_withdrawal_amount DECIMAL(10,2) DEFAULT 0, withdrawal_fee_rate DECIMAL(5,4) DEFAULT 0, auto_approval_enabled BOOLEAN DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### 提现规则检查 ```go // 伪代码 func ValidateWithdrawalRequest(agentID uint, amount float64) error { setting := db.FindWithdrawalSetting(agentID) // 检查最小金额 if amount < setting.MinWithdrawalAmount { return fmt.Errorf("提现金额不能低于 %.2f 元", setting.MinWithdrawalAmount) } // 检查最大金额 if setting.MaxWithdrawalAmount > 0 && amount > setting.MaxWithdrawalAmount { return fmt.Errorf("提现金额不能高于 %.2f 元", setting.MaxWithdrawalAmount) } // 检查账户余额 balance := db.GetAgentBalance(agentID) fee := amount * setting.WithdrawalFeeRate totalAmount := amount + fee if balance < totalAmount { return fmt.Errorf("余额不足,需要 %.2f 元(含手续费 %.2f 元)", totalAmount, fee) } return nil } ``` --- ## 分佣业务流程示例 ### 示例 1: 一次性分佣 ``` 1. 用户购买套餐(100元) ↓ 2. 订单完成 ↓ 3. 触发分佣计算 - 规则: 一次性分佣,固定金额 10元 - 创建分佣记录: agent_id=123, commission_amount=10.00, status=1 待发放 ↓ 4. 自动发放 - 更新分佣记录: status=2 已发放, distributed_at=NOW() - 更新代理账户余额: balance += 10.00 ↓ 5. 完成 ``` --- ### 示例 2: 长期分佣(OR 条件解冻) ``` 1. 用户购买套餐(100元) ↓ 2. 订单完成 ↓ 3. 触发分佣计算 - 规则: 长期分佣,10%,冻结30天 OR 使用1GB流量 - 创建分佣记录: agent_id=123, commission_amount=10.00, status=3 已冻结 - 解冻条件: {"time_based": {"days": 30}, "data_based": {"data_mb": 1024}} ↓ 4. 定时任务检查解冻条件 - 时间检查: 30天后 → 满足条件 → 解冻 - 流量检查: 使用1GB流量后 → 满足条件 → 解冻 ↓ 5. 自动解冻 - 更新分佣记录: status=2 已发放, unfrozen_at=NOW(), distributed_at=NOW() - 更新代理账户余额: balance += 10.00 ↓ 6. 完成 ``` --- ### 示例 3: 组合分佣 ``` 1. 用户购买套餐(100元) ↓ 2. 订单完成 ↓ 3. 触发分佣计算 - 规则: 组合分佣 - 一次性条件: 固定金额 5元 - 长期条件: 固定金额 10元,冻结30天 ↓ 4. 创建两条分佣记录 - 记录1: agent_id=123, commission_amount=5.00, status=1 待发放 - 记录2: agent_id=123, commission_amount=10.00, status=3 已冻结 ↓ 5. 立即发放一次性分佣 - 记录1: status=2 已发放 - 代理账户余额: balance += 5.00 ↓ 6. 30天后自动解冻长期分佣 - 记录2: status=2 已发放 - 代理账户余额: balance += 10.00 ↓ 7. 完成 ``` --- ## 监控和统计 ### 分佣统计指标 1. **代理分佣总额** - 待发放金额 - 已发放金额 - 已冻结金额 2. **分佣发放效率** - 平均发放时长 - 平均解冻时长 3. **提现统计** - 提现申请数量 - 提现成功率 - 提现金额统计 ### SQL 查询示例 ```sql -- 1. 代理分佣总额统计 SELECT agent_id, SUM(CASE WHEN status = 1 THEN commission_amount ELSE 0 END) AS pending_amount, SUM(CASE WHEN status = 2 THEN commission_amount ELSE 0 END) AS distributed_amount, SUM(CASE WHEN status = 3 THEN commission_amount ELSE 0 END) AS frozen_amount FROM commission_records WHERE agent_id = 123 GROUP BY agent_id; -- 2. 月度分佣统计 SELECT DATE_FORMAT(created_at, '%Y-%m') AS month, COUNT(*) AS total_records, SUM(commission_amount) AS total_amount FROM commission_records WHERE agent_id = 123 AND status = 2 GROUP BY DATE_FORMAT(created_at, '%Y-%m') ORDER BY month DESC; -- 3. 提现统计 SELECT status, COUNT(*) AS request_count, SUM(withdrawal_amount) AS total_amount FROM commission_withdrawal_requests WHERE agent_id = 123 GROUP BY status; ``` --- ## 最佳实践 ### 1. 合理设置冻结条件 - **过短**: 可能导致代理流失 - **过长**: 影响代理积极性 - **建议**: 根据业务特点和用户留存数据设置合理的冻结期 ### 2. 使用 OR 条件解冻 - **优势**: 提高解冻灵活性,代理满足任一条件即可获得佣金 - **示例**: 30天 OR 1GB流量,满足其一即可解冻 ### 3. 启用阶梯奖励 - **优势**: 激励代理提高订单量 - **示例**: 月订单量越多,单笔佣金越高 ### 4. 定期审查分佣规则 - 定期分析分佣数据,优化分佣规则 - 根据代理反馈调整冻结条件和佣金比例 --- ## 总结 IoT SIM 管理系统的分佣系统具有以下特点: 1. **三种分佣模式**: 一次性分佣、长期分佣、组合分佣 2. **阶梯奖励机制**: 支持根据订单数量设置不同的分佣标准 3. **OR 条件解冻**: 时间到期 OR 流量达标,满足任一条件即可解冻 4. **自动 + 手动审批**: 支持自动解冻和手动审批两种模式 5. **分佣模板**: 快速创建分佣规则,避免重复配置 6. **运营商结算**: 记录与运营商的月度结算情况 7. **提现管理**: 完善的提现申请和审批流程 8. **多级代理**: 支持无限层级的代理树形结构 通过灵活配置和使用分佣系统,可以激励代理积极性,提高销售业绩,实现平台与代理的双赢。 --- **文档版本**: v1.0 **最后更新**: 2026-01-12 **维护人员**: Claude Sonnet 4.5