# 企业邀请赠水(2026-10-19) 第一版为企业邀请企业:新企业首购前绑定邀请企业,首购后完成对应规格的后续完整配送签收,后台核实后向邀请企业发放水权益。奖励与代理佣金分别记账,不产生现金余额或提现,不增加实物库存。本次不实现自动送水。 ## 配置与使用 1. 执行 `php -d extension=mbstring scripts/migrate_water_promotion.php` 只查看计划;加 `--apply` 新建三张 InnoDB 表,初始化关闭的规则。复跑不覆盖已有配置,不回填历史订单或奖励。 2. 使用新后台构建并重载本项目 Webman,使新增路由及代码生效。入口:**财务结算中心 → 推广赠水奖励**。只读沿用 `water:finance:read`,配置及审核沿用 `water:finance:write`,接口仍实时核对账号、角色和权限状态。 3. 配置赠水规格、每次赠送桶数及首笔收款金额门槛(整数分,0表示不设额外门槛),开启新邀请。活动默认关闭,桶数默认0,无虚构奖励金额。 4. 邀请企业管理员在小程序“我的 → 奖励与推广”获取企业唯一邀请码;可复制邀请码,微信小程序可分享对应页面。H5提供复制,不承诺生成微信二维码或海报。 5. 新企业仍由平台建立档案并授权小程序管理员。新企业管理员在首购前输入邀请码并明确确认绑定。分享参数仅保存公开邀请码供登录后填写,不自动创建企业或授予权限。 6. 首笔正金额、非测试购水登记后生成待审核奖励。组合结算虽然生成多张供水收款记录,但首购门槛按整笔结算金额判断,只生成一条奖励。未支付意向、免费收款、测试凭据或测试套餐不触发奖励。 7. 首购后完成对应规格的完整配送签收,财务人员核实真实收款、无退款、非重复客户,填写说明并发放。权益页及权益明细立即可查询对应规格的赠水权益;已发放总桶数不代表剩余可用桶数。 ## 约束和状态 - 企业邀请码为20位随机十六进制码,企业唯一、不可由客户端指定。邀请码不是登录凭据。 - 每个新企业仅可绑定一次邀请人。拒绝自邀、同一管理员管理的企业互邀及循环邀请;已有任何购水记录的企业不能新绑定。未首购的企业可以邀请其他企业,但没有多层邀请分成。 - 绑定保存规则版本、赠水规格、桶数和首购门槛。修改或关闭活动只影响后续邀请码生成及新绑定;已有邀请按原约定审核,不追溯改桶数。 - 状态:`bound` 待首购 → `pending` 待签收及审核 → `issued` 已发放 / `rejected` 不予发放。首笔实际购水低于门槛直接不予发放,后续订单不能替代首购。审核驳回不可通过重复请求改成发放。 - 唯一约束、行锁及 request_key 保证重复请求不重复绑定或发奖。规则和审核均检查 revision;审核终态的相同结果及说明可幂等重放。 - 首购时保存已有配送任务的最大ID;发放仅接受之后新建的、对应企业和首购规格的完整签收,避免同一秒时间戳或旧签收误领奖。赠水规格可以与首购规格不同。 - 权益仍按企业和SKU汇总,配送未逐桶分摊到购水订单,因此此条件表示“首购后的对应规格签收”,不证明整笔组合订单已全部履约,必须结合人工核实。 - 奖励记录、权益增加和 `promotion_reward` 流水在同一事务;失败全部回滚。赠水后配送继续校验仓库库存并冻结权益,不预先创造库存。 - 小程序只返回授权企业的邀请及奖励状态,不向邀请企业披露被邀请企业的付款凭据、金额、配送ID或后台核实说明。 - 正式退款及已用奖励扣回尚未实现;第一版必须人工审核后发放,不能视为自动退款闭环。微信登录、域名、真机分享需要原有微信配置完成。 - 旧的本机推广演示种子不再作为真实奖励返回,不删除历史演示流水。 ## 数据与接口 新增 `sa_water_promotion_setting`(平台配置)、`sa_water_promotion_code`(企业邀请码)、`sa_water_promotion_referral`(关系、规则及首购快照、奖励状态)。没有 Redis、队列或外部付款调用。 小程序已有 `GET /api/mini/v1/enterprises/{enterprise}/rewards?page=1` 返回真实记录,每页20条。新增: - `POST /api/mini/v1/enterprises/{enterprise}/promotion/code`:`{request_key}`,仅企业管理员。 - `POST /api/mini/v1/enterprises/{enterprise}/promotion/bind`:`{request_key, invite_code}`,仅企业管理员。 后台新增: - `GET /core/water/finance/promotion?page=1&status=pending`:配置及分页奖励记录。 - `POST /core/water/finance/promotion/policy`:`{enabled, sku_id, quantity, min_amount_cents, revision}`。 - `POST /core/water/finance/promotion/review`:`{id, revision, decision, note, receipt_refund_checked}`;decision 为 issued/rejected,发放须显式核实标记为true。 收款入口:`WaterPurchaseReceipt::issue` → `PromotionReferrals::purchased`;小程序控制器 → `PromotionService`(权限/幂等)→ 领域服务 → Eloquent模型;后台控制器沿用财务权限,委托配置、查询及审核服务。没有通过控制器查询业务表。 OpenAPI维护源为 `docs/openapi/water-mini-v1.json`,通过 `php scripts/build_mini_docs.php` 同步公开文档、`npm run api:types` 生成小程序类型。 ## 验证与回退 `php -d extension=mbstring tests/water_promotion_test.php` 使用真实数据库事务,覆盖活动开关、规则版本、自邀/重复/共用管理员/循环绑定、权限撤销、首购、旧签收拒绝、完整签收、规则快照、组合结算、重试、驳回、财务信息隔离及失败回滚。结束比较策略、邀请、权益、收款和流水快照,所有业务夹具回滚。 回退时先关闭新邀请,保留新增表、已发放权益及审计流水;不得删除已生效权益或账本。需要回退代码时先停用新增接口入口,再使用对应旧版本构建。关闭活动不撤销已发放权益,也不取消已有绑定的约定。