订阅提成最容易被误做成“每月固定金额乘比例”,但企业实际关心的是按哪个计划、哪个销售、哪个事件日期算,以及历史金额如何按当天汇率折算。
核心链路
commission_plan_achievement.py先把 achievementtype扩成mrr,再加recurring_plan_id。但它同时用_constrains_type_mrr()立了边界:MRR 规则不能再附带 product / category 约束,而普通 SO achievement 也不能混入 recurring plan。achievement_report.py里_get_subscription_currency_rates()生成专门的汇率 CTE,按 conversion_date 找各币种在公司维度下的最近汇率。订阅提成不是拿今天汇率随便折一下。_get_filtered_order_log_cte()把sale_order_log作为主事实表,并按 user/team/date window 截取事件;真正被统计的是 log 事件,而不是当前订单表上的一个瞬时字段。_subscription_lines()再把 rules、filtered_order_logs、sale_order、汇率表拼成 team/user 两条 commission line CTE,且只统计effective_date IS NOT NULL的记录。也就是说,没真正生效的订阅变更不会进入提成。- 最终的主链路是:commission rule 约束 -> recurring plan 过滤 -> sale_order_log 事件 -> 汇率换算 -> team/user achievement 聚合。它比“每月跑一遍合计金额”严谨得多。
关键源码位置
/home/ubuntu/odoo-temp/enterprise/sale_commission_subscription/model/commission_plan_achievement.py/home/ubuntu/odoo-temp/enterprise/sale_commission_subscription/report/achievement_report.py
容易误解的地方
- 误区一:MRR 提成还能再叠加产品分类条件。源码明确禁止这种混搭。
- 误区二:订阅当前 MRR 就是提成基数。企业版看的是
sale_order_log的事件记录。 - 误区三:续费、升级、降级都应同权计入。没有
effective_date的记录不会入账。
实战注意事项
- 如果业务要按不同订阅 plan 分不同提成,优先使用
recurring_plan_id,不要靠手工过滤报表。 - 出现历史 MRR 提成偏差时,先看 log 的
event_date/effective_date,再看汇率基准日。 - 团队规则与个人规则会走两套 CTE,设计方案时要先想好“团队共享功劳”还是“个人独占功劳”。
结语
企业版这些代码共同说明一件事:真正可上线的业务流程,靠的不是“页面上看起来能点通”,而是权限、状态、时机、对账口径和跨模块回写都被收紧。理解这些边界,实施和二开时就不容易走进“功能演示能跑、真实业务一用就散”的坑。
DISCUSSION
评论区