diff --git a/docs/合伙股东收益体系二次开发文档.md b/docs/合伙股东收益体系二次开发文档.md new file mode 100644 index 0000000..22cb344 --- /dev/null +++ b/docs/合伙股东收益体系二次开发文档.md @@ -0,0 +1,860 @@ +# 恒连数通 · 合伙股东收益体系完整技术方案 + +> 版本:V2.0(基于现有前后端代码重写) +> 日期:2026-09-16 +> 代码基线:本仓库 Shopro Plus **3.2.0** + FastAdmin +> 用户端基线:官方 **sheep uni-app**(`SHOPRO_API_PATH=/addons/shopro/`) +> 状态:可排期实施方案(业务未拍板项见第 16 节,开发按建议默认) + +--- + +## 0. 先说清楚现在仓库里有什么 + +| 部分 | 位置 | 结论 | +|---|---|---| +| 商城后端 | 本仓库 `addons/shopro`、`application/admin` | 完整,Shopro Plus 3.2.0 | +| 管理后台前端 | 本仓库 `application/admin/view/shopro` + `public/assets/js/backend/shopro` | 完整,Element Plus + RequireJS | +| 用户端 uni-app | **不在本仓库** | 官方 sheep 结构,接口已备好;本地未找到恒连数通前端工程 | +| 现有分销 | 三级百分比佣金 + 分销商等级升级 | 能复用关系链 / 支付钩子 / 钱包 / 团队统计,**不能直接算**固定金额奖、均分、马豆、释放券 | + +用户端若已上线,一般是独立 sheep 工程,请求前缀: + +``` +{SHOPRO_BASE_URL}/addons/shopro/{controller.action} +Header: token + platform +``` + +对照本地另一套 Shopro Plus 前端(`/Users/chen/Desktop/xbiuld/理发店`),页面和接口命名与本后端完全对得上。本方案用户端改动按这套 sheep 写。**开工前请把恒连数通 uni-app 放进工作区。** + +--- + +## 1. 现有代码如何运转(必须顺着改,不能另起炉灶) + +### 1.1 关系链 + +- 字段:`fa_user.parent_user_id` + - `NULL` = 未锁定 + - `0` = 平台直推 + - `>0` = 上级用户 +- 绑定只发生一次:`addons/shopro/service/commission/Agent.php::bindUserRelation()` +- 绑定时机由 `shop.commission.invite_lock` 决定:`share` / `pay` / `agent` +- 当 `become_agent.type = user` 时,锁定事件被强制成 `agent`(注册即绑) +- 后台改上级:`shopro/commission/agent/changeParentUser`,已有环检测 + +**本体系全部「直推 / 伞下 / 关系链」继续只用这一条链,禁止再做第二套推荐关系。** + +### 1.2 支付后分销(现网真实链路) + +``` +PayOper 支付成功 + → Queue shopro-high : OrderPaid@paid + → Hook order_paid_after + ① listener\Order::orderPaidAfter + 累计 user.total_consume、发货 + ② listener\Commission::orderPaidAfter + bindUserRelation('pay') + 每个 order_item: + OrderService::checkAndSetCommission() + createCommissionOrder() // fa_shopro_commission_order + runCommissionPlan() // 按 1/2/3 级百分比写 fa_shopro_commission_reward + RewardService('paid')::runCommissionRewardByOrder() + createNewAgent() + createAsyncAgentUpgrade() // Queue shopro : Commission@agentUpgrade +``` + +积分订单 `order.type === 'score'` 整单跳过。 +货到付款走 `order_offline_paid_after`,同一套逻辑。 + +结算节点由 `shop.commission.reward_event` 控制:`paid` / `confirm` / `finish`。 +入账:`Wallet::change($user, 'commission', $amount, 'reward_income')`。 + +### 1.3 退款回滚 + +唯一有效钩子:`order_item_refund_after` → `Commission::orderItemRefundAfter`。 +售后完成本身(`order_aftersale_completed`)**不会**回滚佣金,必须发生真实退款。 + +回滚受两个开关控制: + +- `shop.commission.refund_commission_reward` +- `shop.commission.refund_commission_order` + +已入账用 `reward_back` 扣佣金钱包(允许扣成负)。 + +### 1.4 钱包(只有三种) + +`Wallet::change()` 白名单:`money` / `score` / `commission`。 +对应 `fa_user` 三列 + `fa_shopro_user_wallet_log`。 + +现有佣金事件:`reward_income` / `reward_back` / `withdraw` / `withdraw_error` / `transfer_to_money`。 + +**现金类新收益全部进 `commission`,加新 event,不要新开第四种可提现钱包。** +马豆、兑换券不能塞进这三种,否则流水和提现会乱。 + +### 1.5 分销商与升级 + +表:`fa_shopro_commission_agent`(主键 `user_id`) + +已有业绩字段(升级引擎直接用): + +- `child_order_count_0/1/2/all`、`child_order_money_*` +- `child_user_count_*`、`child_agent_count_*` +- `child_agent_level_1`、`child_agent_level_all`(JSON,可配「伞下有 N 个某等级」) + +升级:`Agent::runAgentUpgradePlan()` → `isMatchUpgradeLevelRule()`。 +条件可配:消费、直推人数、团队订单数、伞下某等级人数。 +`upgrade_type=0` 满足一条即可,`=1` 必须全满足。 + +成为分销商:`shop.commission.become_agent.type` + +| type | 含义 | +|---|---| +| `user` | 注册即是 | +| `goods` | 买指定商品 | +| `consume` | 累计消费达标 | +| `apply` | 自行申请 | + +### 1.6 用户端现有接口(sheep 已对接) + +| sheep 调用 | 后端 | 现状 | +|---|---|---| +| `GET commission.agent` | `addons/shopro/controller/commission/Agent::index` | 返回 agent + `level_info.name/image`,未成为则 code 100 | +| `GET commission.agent/team` | 同上 `team` | **只查直推** `parent_user_id=我` | +| `GET commission.order` | `commission/Order::index` | 分销订单 + 本人 rewards | +| `GET commission.log` | `commission/Log::index` | 动态 | +| `POST commission.agent/transfer` | 佣金转余额 | 已可用 | +| `GET user.user/profile` | `user/User::profile` | money / commission / score,**无身份徽章字段** | +| `GET user.wallet_log?type=commission` | 佣金流水 | event 文案来自 WalletLog::$eventMap | +| `GET user.coupon` | Shopro 优惠券 | **一次性券,不能按天释放** | + +分销中心关闭条件:`shop.commission.level == 0` → 接口直接 101。 +**禁止把 level 设成 0 来关旧百分比**,否则整个「分销中心」前端挂掉。 + +### 1.7 管理后台现有页 + +`shopro/commission` 下已有:分销商、等级、分销订单、佣金、动态、分销商品。 +配置页:`shopro/config/commission`。 +等级编辑页文案仍是「等级佣金比例」,要改成「创客级差金额」。 + +### 1.8 定时任务现状 + +**没有日结 cron。** +`Shopro::appInit()` 只注册了 `shopro:chat`、`shopro:help`。 +队列:`shopro-high`(支付)、`shopro`(升级 / 自动收货)。 +优惠券没有「每天释放一点」的能力。 + +--- + +## 2. 总体策略:在 Shopro 分销内核上长一层,不新开插件 + +上一版「独立 `addons/partner`」在对账、退款、前端上会和现网裂开。V2 改为: + +``` +保留 + parent_user_id + 成为分销商 / 升级队列 + 团队人数与订单统计 + 支付 / 退款钩子 + 佣金钱包 + 提现 + 转余额 + sheep 分销中心页面骨架 + +关掉(配置,不删代码) + runCommissionPlan 的百分比 1/2/3 级分佣 + +新增 + 身份扩展(酒道馆 / 区县) + 固定金额结算器 PartnerReward + 马豆账户 + 汇率 + 兑换券释放计划 + 00:30 日结命令 + 后台规则页 + 流水页 + sheep 徽章 / 马豆 / 兑换券页 +``` + +原则: + +1. 旧 `runCommissionPlan` 用开关跳过,历史佣金不动。 +2. 新收益写入新表 `fa_shopro_partner_reward`,现金入账仍走 `Wallet::change(..., 'commission', ...)`。 +3. 用户端继续打 `commission.agent`,只扩展返回字段和加少量新接口。 +4. 品酒师 ↔ 创客互斥,用 `agent.level` 表达,不再做第二套等级。 + +--- + +## 3. 身份如何落到现有表 + +### 3.1 等级复用 `fa_shopro_commission_level` + +上线时初始化 7 条等级(后台可改名称和徽章图): + +| level | 名称 | 业务身份 | 单笔极差基数(建议) | +|---|---|---|---| +| 1 | 品酒师 | 普通会员 | 0(不参与极差) | +| 2 | 创客V1 | 合伙股东·创客 | 20 | +| 3 | 创客V2 | 合伙股东·创客 | 40 | +| 4 | 创客V3 | 合伙股东·创客 | 60 | +| 5 | 创客V4 | 合伙股东·创客 | 80 | +| 6 | 创客V5 | 合伙股东·创客 | 100 | +| 7 | 创客V6 | 合伙股东·创客 | 120 | + +判定: + +``` +是品酒师 = agent 存在且 level == 1 +是创客 = agent 存在且 level >= 2 +合伙股东 = 创客 或 酒道馆 或 区县代理 +``` + +一个人只有一个 `level`,所以**不可能同时是品酒师和创客**,与需求一致。 +创客继承品酒师收益:结算器判断「品酒师奖」时用 `level >= 1`,不要求 `== 1`。 + +### 3.2 酒道馆 / 区县:加在 agent 上,不新建用户身份表 + +```sql +ALTER TABLE `fa_shopro_commission_agent` + ADD COLUMN `is_venue` tinyint(1) NOT NULL DEFAULT 0 COMMENT '酒道馆' AFTER `level`, + ADD COLUMN `is_county` tinyint(1) NOT NULL DEFAULT 0 COMMENT '区县代理' AFTER `is_venue`, + ADD COLUMN `county_code` varchar(20) NOT NULL DEFAULT '' COMMENT '区县编码' AFTER `is_county`, + ADD COLUMN `direct_order_seq` int(11) NOT NULL DEFAULT 0 COMMENT '直推合格单累计(推三返一)' AFTER `county_code`, + ADD COLUMN `madow` decimal(20,8) NOT NULL DEFAULT 0.00000000 COMMENT '马豆' AFTER `direct_order_seq`, + ADD COLUMN `voucher_total` decimal(12,2) NOT NULL DEFAULT 0.00 AFTER `madow`, + ADD COLUMN `voucher_released` decimal(12,2) NOT NULL DEFAULT 0.00 AFTER `voucher_total`, + ADD COLUMN `voucher_used` decimal(12,2) NOT NULL DEFAULT 0.00 AFTER `voucher_released`, + ADD KEY `idx_venue` (`is_venue`), + ADD KEY `idx_county` (`is_county`); +``` + +可叠加:创客V5 + 酒道馆 + 区县代理 是合法的。 + +「30 日必须有自己的订单」用现成 `fa_user` + 订单表查,不冗余存;可加缓存字段 `last_self_order_time` 到 agent,支付成功时更新,日结用索引扫。 + +```sql +ALTER TABLE `fa_shopro_commission_agent` + ADD COLUMN `last_self_order_time` bigint(16) DEFAULT NULL COMMENT '本人最近合格订单时间' AFTER `voucher_used`, + ADD KEY `idx_last_self_order` (`last_self_order_time`); +``` + +### 3.3 注册即品酒师(建议默认) + +后台把分销设置改成: + +- `become_agent.type = user`(注册即分销商) +- `agent_check = 0` +- `agent_form.status = 0` +- `invite_lock` 保持 `share`(分享即锁上级;因 become=user 时代码会改成 `agent`,需改一处,见 7.2) +- `self_buy` 按业务,推三返一默认不含自购 +- `reward_event = paid` +- `level` 保持 `>= 1`(分销中心开着) +- 新增 `shop.commission.partner_mode = 1`(跳过百分比分佣) + +需求里「直推 3 单或伞下有人升级才是品酒师」与「默认都是品酒师」冲突。 +**开发按注册即 level=1。** 若改口,再把 `become_agent` 换成 `goods/consume` 或自定义升级到 level=1。 + +### 3.4 创客 / 酒道馆 / 区县怎么来(需求未写) + +| 身份 | 建议默认 | 现成能力 | +|---|---|---| +| 创客 V1-V6 | 后台改 `agent.level`;同时把 V2-V6 的 `upgrade_rules` 配上(直推人数、团队单数、伞下创客数),走现有 `agentUpgrade` 队列 | `shopro/commission/level` + `agent/edit` | +| 酒道馆 | 仅后台勾选 `is_venue` | 新字段,agent 编辑页加开关 | +| 区县代理 | 仅后台勾选 `is_county`,选区县 | 区县数据复用 `shopro/data/area` | + +未拍板前**不要写死**「买某某套餐升酒道馆」。升级条件全部进等级规则 JSON。 + +--- + +## 4. 计奖总闸 + +### 4.1 合格订单 + +与现网分销对齐,减少口径分裂: + +- `fa_shopro_order`,`type != score` +- 状态 `paid` 或 `completed` +- 商品 `fa_shopro_commission_goods.status = 1`(继续用「是否参与分销」当「是否参与本体系」) +- 实付 `pay_fee > 0` +- **计 1 单 = 1 个订单头**(不按件数)。推三返一、团队拆分、平台均分、汇率 N 同一口径 + +`createCommissionOrder()` 今天按 **order_item** 写业绩。partner_mode 下: + +- 仍写一条 `shopro_commission_order`(沿用退款钩子、业绩、升级) +- 但 `runCommissionPlan` 不跑 +- `PartnerReward` **按订单头只算一次**(用 `order_id` 幂等,不按 item 乘倍数) + +### 4.2 30 日活跃 + +``` +active = 存在本人合格订单 + AND paid_time >= 今日0点 - 29天 -- 含今天共 30 个自然日 +``` + +实现:优先 `agent.last_self_order_time`,没有则查订单。 + +| 奖项 | 不活跃时 | +|---|---| +| 推三返一 / 极差 / 平级 / 团队拆分 | 该受益人跳过,**不顺延**给再上一级;极差**不占用水位** | +| 平台均分(酒道馆 100、区县 50、马豆) | 不进分母 | +| 买家兑换券 | 本次下单即活跃,照发 | + +### 4.3 关系链遍历 + +新建 `addons/shopro/service/partner/ChainService.php`: + +``` +从 buyer.parent_user_id 向上走 +最多 partner.chain_max_depth(默认 50) +只收集 agent.status in (normal, freeze) +返回节点:user_id, level, is_venue, is_county, last_self_order_time +``` + +复用 `Agent::getParentUserId()`,不要 SQL 递归。 + +--- + +## 5. 收益规则(算法冻结稿) + +现金一律进佣金钱包。马豆、兑换券进 agent 扩展字段。 + +### 5.1 品酒师 · 推三返一 + +业务对齐:398 + 400 + 600 = **1398**(推 3 单返 1 件货的钱),之后循环。 + +- 受益人:买家直推上级,且 `level >= 1`,且 30 日活跃 +- 自购不发 +- 序号:`agent.direct_order_seq`(受益人维度,每成功计 1 次 +1) + +``` +seq = (direct_order_seq % 3) // +1 之后 +amount = [398, 400, 600][ (seq-1) % 3 ] +``` + +退款:金额 `reward_back`,`direct_order_seq -= 1`(≥0),下一单顶原序号。 + +### 5.2 品酒师 · 每日 1:1 + 马豆汇率 + +原文若按现金 1:1 发当天 GMV,毛利为负。 +**默认:发马豆,只展示人民币价值,不能提现。** + +日结(昨天 00:00:00–23:59:59): + +``` +G = 昨日合格订单 pay_fee 合计 +users = last_self_order_time 落在 [昨天-29天, 昨天] 的品酒师/创客(level>=1, status 可用) +每人马豆 = G / count(users) // 8 位小数,尾差进平台账户 user_id=0 +``` + +汇率: + +``` +base = 0.00000075 +n = 配置 partner.madow.step_orders,默认 1 +N = 平台历史合格订单累计(支付成功;退款默认不减) +rate = base * floor(N / n) +展示价值 = agent.madow * rate +``` + +`N`、`rate` 每天写入 `fa_shopro_partner_rate_log`,前端读最新一行。 + +### 5.3 品酒师 · 兑换券 1.5 倍 / 365 天 + +不进 `fa_shopro_coupon`(那是一次性优惠券)。 + +``` +总额 = 订单实付 * 1.5 // 1398 → 2097 +次日 00:30 起释放 365 天 +每天 = 总额/365,最后一天补尾差 +可用 = released - used +``` + +结算抵扣:在 `OrderCreate` 增加 `voucher_fee`,扣 `voucher_used`。可与余额混付。默认不过期、不转赠。 + +### 5.4 创客 · 极差奖 + +基数:`level_bonus = {2:20, 3:40, 4:60, 5:80, 6:100, 7:120}`,后台可改。 +从近到远扫链上 `level>=2` 且活跃的创客: + +``` +seen = 0 +for agent in chain_makers: + cap = level_bonus[agent.level] + if cap <= seen: continue // 平级或更低,无极差 + pay = cap - seen + 入账 pay + seen = cap +``` + +例:V1(level2) → V3(level4) → V6(level7) = 20 + 40 + 60。 +不活跃的人跳过且不抬 `seen`。 + +### 5.5 创客 · 平级 10% / 被超越 5% + +与示例「V5 的 100 × 10% = 10」对齐:基数用**等级标准佣金**,不是本单极差实得。 + +- 平级:刚拿到极差的人再向上,**最近一个同 level** 得 `level_bonus × 10%`,只一层 +- 被超越:向上**最近一个 level 更低的创客**得 `本次最高水位基数 × 5%`,每单都算,只一层 + +### 5.6 酒道馆 / 区县 · 团队拆分(方案 I,防重复) + +一单只切 **100 元**,不要酒道馆先拿 50 再拿区县那 50。 + +``` +nearest_venue = 链上最近 is_venue=1 且活跃 +nearest_county = 链上最近 is_county=1 且活跃 + (若有酒道馆,区县必须在该酒道馆之上) + +无酒道馆有区县:区县 100 +有酒道馆有区县:酒道馆 50 + 其上最近区县 50 +有酒道馆无区县:酒道馆 50 +都无:不发 +自购且自己是酒道馆:自己算最近酒道馆 +``` + +### 5.7 酒道馆平级 10% + +基数 = 本单该下级的 `team_venue`(50),**不含**创客收益、**不含**平台均分。 +向上最近一个酒道馆拿 5 元。 + +### 5.8 区县平级 10% + +基数 = 本单该下级的 `team_county`(50 或 100)。 +向上最近一个区县拿 10%。 + +### 5.9 平台均分(日结) + +| 奖池 | 公式 | 分母 | +|---|---|---| +| 酒道馆 | 昨日单数 × 100 | `is_venue=1` 且活跃 | +| 区县 | 昨日单数 × 50 | `is_county=1` 且活跃 | + +分母为 0:进平台账户。尾差进平台。 +与 5.2 同一条日结命令,00:30 跑昨天。 + +--- + +## 6. 一单拆账示例 + +买家 U0,链:U1 品酒师 → U2 创客V5 → U3 创客V5 → U4 创客V6+酒道馆 → U5 区县。 +U1 直推本单是第 1 单,全部活跃。实付 1398。 + +| 人 | 即时现金 | 说明 | +|---|---|---| +| U1 | 398 | 推三返一 | +| U2 | 100 | 极差 V5 | +| U3 | 10 | 平级 10% | +| U4 | 20 + 50 | 极差 20 + 酒道馆拆分 50 | +| U5 | 50 | 区县拆分 50 | +| U4 的上级酒道馆 | 5 | 酒道馆平级 | +| U5 的上级区县 | 5 | 区县平级 | + +U0:兑换券额度 2097。 +日结另计:酒道馆均分、区县均分、马豆。 + +--- + +## 7. 后端改哪些文件 + +### 7.1 新增 + +``` +addons/shopro/service/partner/ChainService.php +addons/shopro/service/partner/ActiveService.php +addons/shopro/service/partner/PartnerRewardService.php // 订单即时奖入口 +addons/shopro/service/partner/Push3Reward.php +addons/shopro/service/partner/MakerDiffReward.php +addons/shopro/service/partner/MakerPeerReward.php +addons/shopro/service/partner/TeamSplitReward.php +addons/shopro/service/partner/PeerShareReward.php +addons/shopro/service/partner/DailySettleService.php +addons/shopro/service/partner/MadowService.php +addons/shopro/service/partner/VoucherService.php +addons/shopro/service/partner/RateService.php +addons/shopro/job/PartnerSettle.php // 队列:单笔订单 +addons/shopro/console/PartnerSettle.php // php think shopro:partner:settle +addons/shopro/controller/partner/Index.php // 用户端:概览/马豆/兑换券/流水 +application/admin/controller/shopro/partner/Reward.php +application/admin/controller/shopro/partner/Daily.php +application/admin/controller/shopro/partner/Voucher.php +application/admin/model/shopro/partner/Reward.php +application/admin/model/shopro/partner/RateLog.php +application/admin/model/shopro/partner/VoucherPlan.php +application/admin/model/shopro/partner/DailyReport.php +``` + +SQL 放 `addons/shopro/upgrade/partner_v2.sql`,手工执行(本项目没有自动 migration)。 + +### 7.2 必改的现有文件(尽量小) + +| 文件 | 改什么 | +|---|---| +| `addons/shopro/hooks.php` | `order_paid_after` / `order_offline_paid_after` / `order_item_refund_after` 增加 `listener\Partner` | +| `addons/shopro/listener/Partner.php` | **新建**。支付入队 `PartnerSettle`;退款调回滚。不改 `Commission.php` 主体 | +| `addons/shopro/service/commission/Order.php::runCommissionPlan` | 若 `sheep_config('shop.commission.partner_mode')` 则直接 return | +| `addons/shopro/service/commission/Config.php` | `getInviteLockEvent()`:partner 模式下 become=user 仍允许 `invite_lock=share`,否则注册即绑会丢掉分享关系 | +| `addons/shopro/service/commission/Agent.php` | 支付后更新 `last_self_order_time`;`createNewAgent` 默认 level=1 | +| `application/admin/model/shopro/commission/Agent.php` | 新字段、append 身份文案 | +| `addons/shopro/controller/commission/Agent.php::index` | 返回值加 `identities` / `madow` / `madow_value` / `voucher_*` / `rate` | +| `addons/shopro/controller/user/User.php::profile` | 附加轻量身份(徽章用,避免再打一次 agent) | +| `application/admin/model/shopro/user/WalletLog.php` | eventMap 增加 `push3` `maker_diff` `maker_peer` `maker_overtaken` `team_venue` `team_county` `venue_peer` `county_peer` `venue_share` `county_share` | +| `addons/shopro/Shopro.php::appInit` | 注册 `shopro:partner:settle` | +| `addons/shopro/service/order/OrderCreate.php` | 兑换券抵扣 | +| `application/admin/controller/shopro/commission/Agent.php` | 编辑页:酒道馆/区县开关 | +| `application/admin/controller/shopro/Config.php` | 分销配置增加 partner 分组 | +| `addons/shopro/config/menu.php` | 菜单:收益流水、日结、兑换券 | + +`Wallet::change` 的 `$event` 是自由字符串,**不用改 Wallet.php**,只要补 eventMap 文案。 + +### 7.3 支付 / 退款时序(改完后) + +``` +order_paid_after + Commission::orderPaidAfter // 写 commission_order、升级、(partner_mode 跳过百分比) + Partner::orderPaidAfter + 更新 last_self_order_time + Queue::push PartnerSettle@order, {order_id}, shopro-high + +PartnerSettle@order + 锁 order_id + 推三返一 / 极差 / 平级 / 团队拆分 / 角色平级 + 写 voucher_plan + N += 1(内存计数表或 rate 服务) + Wallet::change commission + 各 event + 每条 partner_reward 唯一键防重 + +order_item_refund_after + Commission 原逻辑(业绩) + Partner::refund + 回滚该 order_id 下 status=1 的即时奖 + 推三返一序号 -1 + 关闭兑换券计划并扣未使用已释放 + 日结均分 / 马豆 / 汇率 N 不回溯 +``` + +--- + +## 8. 新表 + +### 8.1 `fa_shopro_partner_reward` + +```sql +CREATE TABLE `fa_shopro_partner_reward` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `order_id` int(11) NOT NULL DEFAULT 0, + `buyer_id` int(11) NOT NULL DEFAULT 0, + `user_id` int(11) NOT NULL COMMENT '受益人', + `role` varchar(20) NOT NULL DEFAULT '' COMMENT 'taster/maker/venue/county/system', + `reward_type` varchar(32) NOT NULL, + `amount` decimal(12,2) NOT NULL DEFAULT 0.00, + `madow` decimal(20,8) NOT NULL DEFAULT 0.00000000, + `base_amount` decimal(12,2) NOT NULL DEFAULT 0.00, + `rate` decimal(16,10) NOT NULL DEFAULT 0.0000000000, + `ext` text, + `settle_date` date DEFAULT NULL, + `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '0待入账 1已入账 -1取消 -2退回', + `createtime` bigint(16) DEFAULT NULL, + `updatetime` bigint(16) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_order_user_type` (`order_id`,`user_id`,`reward_type`), + UNIQUE KEY `uk_daily_user_type` (`settle_date`,`user_id`,`reward_type`), + KEY `idx_user` (`user_id`,`reward_type`,`status`), + KEY `idx_order` (`order_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='合伙股东收益'; +``` + +即时奖 `settle_date=NULL`,`order_id>0`。 +日结 `order_id=0`,靠 `uk_daily_user_type` 防重。MySQL 里 NULL 不撞唯一,日结必须写具体日期。 + +`reward_type`:`push3` `maker_diff` `maker_peer` `maker_overtaken` `team_venue` `team_county` `venue_peer` `county_peer` `venue_share` `county_share` `madow_share` `voucher_grant` `voucher_release`。 + +### 8.2 `fa_shopro_partner_voucher_plan` + +```sql +CREATE TABLE `fa_shopro_partner_voucher_plan` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `order_id` int(11) NOT NULL, + `total_amount` decimal(12,2) NOT NULL, + `daily_amount` decimal(12,2) NOT NULL, + `released_amount` decimal(12,2) NOT NULL DEFAULT 0.00, + `released_days` int(11) NOT NULL DEFAULT 0, + `total_days` int(11) NOT NULL DEFAULT 365, + `start_date` date NOT NULL, + `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1释放中 2完成 0关闭', + `createtime` bigint(16) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_order` (`order_id`), + KEY `idx_user_status` (`user_id`,`status`,`start_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +``` + +### 8.3 `fa_shopro_partner_rate_log` / `fa_shopro_partner_daily_report` + +每日一行:`order_count_n, rate, gmv, madow_pool, share_user_count, venue_pool, county_pool`。 +对账表按奖项汇总发放、人数、失败原因。 + +### 8.4 配置(`fa_shopro_config`,分组 `shop.commission.partner`) + +挂在现有分销设置页一个 Tab,不要另做一套 config 体系。 + +| code | 默认 | +|---|---| +| partner_mode | 1 | +| active_days | 30 | +| chain_max_depth | 50 | +| push3_amounts | [398,400,600] | +| madow_mode | madow | +| madow_base_rate | 0.00000075 | +| madow_step_orders | 1 | +| voucher_times | 1.5 | +| voucher_days | 365 | +| maker_bonus | {2:20,3:40,4:60,5:80,6:100,7:120} | +| maker_peer_rate | 0.10 | +| maker_overtaken_rate | 0.05 | +| team_total | 100 | +| venue_split | 50 | +| county_full | 100 | +| venue_share_per_order | 100 | +| county_share_per_order | 50 | +| venue_peer_rate | 0.10 | +| county_peer_rate | 0.10 | + +--- + +## 9. 用户端 API(sheep 风格) + +原接口只扩展字段,前端少改路由。 + +### 9.1 扩展 `GET /addons/shopro/commission.agent` + +在现有 agent 上增加: + +```json +{ + "identities": ["taster"], + "identity_text": "品酒师", + "is_partner": false, + "is_venue": 0, + "is_county": 0, + "madow": "0.00000000", + "madow_rate": "0.00000075", + "madow_value": "0.00", + "voucher_total": "0.00", + "voucher_released": "0.00", + "voucher_used": "0.00", + "voucher_available": "0.00", + "active_30d": true, + "last_self_order_time": 0 +} +``` + +`identities` 例:`["maker","venue"]`,`identity_text`:`合伙股东 · 创客V5 · 酒道馆`。 +徽章继续用 `level_info.name` + `level_info.image`,前端可再画酒道馆/区县小标。 + +### 9.2 扩展 `GET /addons/shopro/user.user/profile` + +加同结构的轻量字段,个人中心不用先打 agent(未成为分销商时 agent 会 100)。 +注册即 agent 后,profile 与 agent 应对齐。 + +### 9.3 新增 `addons/shopro/controller/partner/Index.php` + +| 方法 | 路径 | 作用 | +|---|---|---| +| index | `GET partner.index` | 今日预估、累计、按奖项汇总 | +| rewards | `GET partner.index/rewards` | 分页流水,`reward_type` 筛选 | +| madow | `GET partner.index/madow` | 马豆、汇率历史 | +| voucher | `GET partner.index/voucher` | 计划列表 + 释放日历 | +| daily | `GET partner.index/daily` | 最近日结(均分/马豆) | + +钱包页继续 `user.wallet_log?type=commission`,新 event 会出现中文。 +收益分类明细走 `partner.index/rewards`,因为均分/马豆/券不是 wallet 三种类型能表达的。 + +--- + +## 10. 管理后台(本仓库就能做完) + +### 10.1 改现有页 + +| 页 | 文件 | 改动 | +|---|---|---| +| 分销设置 | `view/shopro/config/index.html` + `js/backend/shopro/config.js` | 增加「合伙股东」Tab | +| 分销商编辑 | `commission/agent` 的 edit | `is_venue` `is_county` `county_code` | +| 分销商列表 | `agent.js` / `agent/index.html` | 筛酒道馆/区县,列身份 | +| 等级 | `commission/level/add.html` | 文案改为级差基数;`commission_rules` 可空;展示 `maker_bonus[level]` | + +### 10.2 新页(照现有 commission 列表复制) + +| 菜单 | 控制器 | 能力 | +|---|---|---| +| 合伙股东 / 收益流水 | `shopro/partner/reward` | 筛选、导出、手工补发/扣回 | +| 合伙股东 / 日结对账 | `shopro/partner/daily` | 按日看池子、重跑昨天 | +| 合伙股东 / 兑换券 | `shopro/partner/voucher` | 计划、已释放、已使用 | + +样式、筛选器、导出照抄 `commission/reward`。 + +--- + +## 11. 用户端 uni-app(sheep,工程不在本仓库) + +对照官方页面,改这些文件即可,不必重做分销中心。 + +### 11.1 必改 + +| 文件 | 改动 | +|---|---| +| `sheep/store/user.js` | `defaultUserInfo` 加 madow / voucher / identities | +| `sheep/api/commission.js` | 已有 agent,不用改 URL | +| `sheep/api/partner.js` | **新建**,对 9.3 | +| `pages/index/user.vue` | 头像下展示身份徽章(品酒师 / 合伙股东) | +| `pages/commission/components/commission-info.vue` | 多徽章:创客等级 + 酒道馆 + 区县 | +| `pages/commission/components/commission-menu.vue` | 增加:收益明细、马豆、兑换券 | +| `pages/commission/index.vue` | 标题可改为「收益中心」 | +| `pages.json` | 注册新页 | + +### 11.2 新页 + +| 路径 | 内容 | +|---|---| +| `/pages/partner/rewards` | 按奖项流水,复用 commission-log 列表样式 | +| `/pages/partner/madow` | 马豆数、汇率、约合人民币、说明 | +| `/pages/partner/voucher` | 总额/已释放/可用、365 进度 | +| `/pages/commission/team` | 直推列表加身份(后端 team 接口 with agent 已有 level,再加 is_venue/is_county) | + +### 11.3 可后做 + +- 兑换专区:下单页勾兑换券,走 `OrderCreate` 的 `voucher_fee` +- 分销商品页:百分比改展示「推三返一 / 极差说明」,或隐藏 + +团队接口今天只返回直推。伞下业绩继续看 agent 上已有的 `child_*`,不必一次拉整棵树。 + +--- + +## 12. 日结与运维 + +``` +# 宝塔 / crontab +30 0 * * * cd /www/wwwroot/qbw.gynhc.com && php think shopro:partner:settle >> /tmp/partner_settle.log 2>&1 +``` + +命令:`addons/shopro/console/PartnerSettle.php` +队列消费者保持现有: + +``` +php think queue:work --queue shopro-high +php think queue:work --queue shopro +``` + +日结步骤: + +1. 文件锁 `runtime/lock/partner_settle_{Ymd}` +2. 统计昨日合格单数、GMV +3. 写汇率快照 +4. 酒道馆均分、区县均分、马豆均分 +5. 释放兑换券一天 +6. 写 daily_report + +同一 `settle_date` 已有成功报告则跳过。后台「重跑」先删当天日结流水再跑。 + +--- + +## 13. 开发分期(按本仓库可交付) + +### P0 · 本仓库后端骨架(约 4–6 天) + +- SQL + agent 字段 +- `partner_mode` 跳过百分比 +- 注册即 level=1(改配置 + Config 邀请锁) +- 推三返一 + 兑换券计划 +- 支付队列 + 退款回滚 +- 日结命令先只做券释放 +- 后台:agent 开关、收益流水列表 +- 扩展 `commission.agent` / `profile` 返回值 + +验收:下一单,直推上级佣金钱包 +398/400/600,买家有券计划。 + +### P1 · 创客极差平级(约 3 天) + +- maker_bonus 配置 +- 极差 + 平级 + 被超越 +- 等级页文案 +- 升级规则用现有 level 后台配 + +### P2 · 酒道馆 / 区县(约 3 天) + +- 团队拆分 100 +- 两种角色平级 +- 日结两份均分 + +### P3 · 马豆(约 2 天) + +- 日结分马豆 +- 汇率快照 +- agent 接口带价值 + +### P4 · 用户端 sheep(另仓,约 4 天,依赖 P0 接口) + +- 徽章、菜单、三页、下单抵扣券 + +### P5 · 对账与售后(约 2 天) + +- 日结重跑、导出 +- 部分退款、券已使用负债 +- 用例回归 + +--- + +## 14. 验收用例(按现网钩子写) + +1. 新注册用户有 `shopro_commission_agent.level=1`,profile 为品酒师。 +2. 分享绑定后 `parent_user_id` 有值(partner 模式不因 become=user 丢掉 share)。 +3. 下级第 1/2/3/4 单,上级佣金流水 event 分别为 push3,金额 398/400/600/398。 +4. `partner_mode=1` 时 `shopro_commission_reward` **不再新增**百分比记录。 +5. 链 V1-V3-V6:20/40/60,佣金 event=`maker_diff`。 +6. 两个 V5:近的 100,远的 10(`maker_peer`)。 +7. 无酒道馆有区县:区县 +100;有两者:50+50,酒道馆平级只抽 50 的 10%。 +8. 上级 31 天无自购:本单他 0 收益,均分进不了分母。 +9. 整单退款:即时奖 `reward_back`,序号回退,券计划关闭。 +10. `php think shopro:partner:settle` 连续跑两次,日结流水不加倍。 +11. 1398 单券总额 2097,第 365 天补尾差。 +12. 同一人同时勾选创客+酒道馆+区县,三套收益都能出,且酒道馆平级不含创客极差。 + +--- + +## 15. 风险(结合现网) + +| 风险 | 现网原因 | 处理 | +|---|---|---| +| 关 `commission.level=0` | Agent 基类直接 101,sheep 分销中心全挂 | 用 `partner_mode` 跳过百分比 | +| become=user 丢掉分享关系 | `getInviteLockEvent()` 强制 `agent` | partner 模式改回尊重 `invite_lock` | +| 按 item 计奖翻倍 | `orderPaidAfter` 循环 items | 即时奖按 `order_id` 幂等一次 | +| 现金 1:1 GMV | 会把当日销售额再发一遍 | 默认马豆 | +| 无 cron | 项目里没有日结命令 | 必须配 crontab,上线检查清单写死 | +| uni-app 不在本仓 | 改完接口用户看不见 | 先交付 API,并行要前端工程 | +| 旧分销数据 | 已有百分比佣金 | 只影响新单;旧单不重算 | +| 队列没开 | 支付钩子已是异步 | 服务器确认 `queue:work` 两个队列都在 | + +--- + +## 16. 仍需业务确认(不回则按括号内默认) + +1. 品酒师:注册即是(默认)还是直推 3 单才是 +2. 1:1:马豆(默认)还是现金 +3. 汇率 n:默认 1;N=全平台累计;退款不减 N +4. 马豆只展示(默认)还是可兑余额 +5. 创客/酒道馆/区县:先全后台开通(默认) +6. 极差:水位差;不活跃不占水位(默认) +7. 平级基数:等级标准佣金;只发一层(默认) +8. 被超越:每单都发(默认) +9. 酒道馆 50 与区县 50:同一笔 100(默认) +10. 计单:订单头;参与分销的商品都算(默认) +11. 30 日:自然日;份额作废不给上级(默认) +12. 区域代理 = 区县代理;不独占行政区(默认) +13. 兑换券:指定分类可兑、可混付、一直累计(默认) +14. 旧百分比:新单关闭(默认) + +--- + +## 17. 建议开工顺序(确认第 16 节后) + +1. 把恒连数通 sheep 工程放进工作区或给仓库地址。 +2. 执行 `upgrade/partner_v2.sql`,改分销配置(become=user、partner_mode=1、七条等级)。 +3. 做 P0:钩子 + 推三返一 + 券计划 + agent 返回值。 +4. 用一笔真实支付单对流水(不要只看代码)。 +5. 再铺 P1–P3,最后对接 uni-app。 + +本仓库当前就能做完 **P0–P3 + 后台**。用户端页面必须有 sheep 工程才能改。 diff --git a/uniapp/uniapp-3.2.0.zip b/uniapp/uniapp-3.2.0.zip new file mode 100644 index 0000000..4ce3b37 Binary files /dev/null and b/uniapp/uniapp-3.2.0.zip differ