# 供水代理商管理 ## 页面与接口 `saiadmin-artd/src/views/water/agents` 是独立代理运营页面,替代通用 WaterWorkspace。页面包含四张统计卡、关键词/等级/授权筛选、每页五行代理列表、本月业绩排行、权限说明、管理抽屉、档案编辑、地图选择服务辖区和账号开通。 - `GET /core/water/agents/dashboard`:列表、全量统计、前四名业绩排行、上级代理选项。 - `GET /core/water/agents/detail?id=...`:档案、关联登录账号、直属下级、最近20家归属企业。 - `POST /core/water/agents`:沿用 save 操作,委托 `WaterAgentManagement` 校验并保存档案与上下级关系。 - `POST /core/water/agents/open-account`:新建档案并开通账号,或为已有未关联账号的档案开通账号;仅超级管理员可执行。 读接口要求 `water:agents:read`,写接口要求 `water:agents:write`,账号开通额外校验管理员ID=1。控制器只处理鉴权、请求及响应;查询/命令分别由 `WaterAgentDashboard`、`WaterAgentManagement` 应用服务处理,策略类位于 `service/agent`。数据读写均经 Eloquent 模型。 ## 数据口径 - 代理总数包含停用档案,本月新增按建档时间统计。 - 企业数是 `sa_water_enterprise.agent_id` 当前关联数量,包含停用客户;业绩从这些企业已登记的供水购水订单汇总,不复用旧充电设备租赁收入或分润比例。 - 顶部成交额为累计值,占比以平台累计购水额为分母;列表和排行为本月截至当前。未来日期订单排除,排名按金额降序、ID升序稳定排序,零成交不虚构排名。 - 历史订单没有成交时的代理快照,因此当前统计按客户**当前归属**汇总;客户转移会改变原代理和新代理的统计。该数据只作经营查询,不直接用作佣金结算依据。 - 团队成员是明确设置上级的下级代理去重数,不含一级及未设置等级的代理;活跃成员为本月有成交且合作启用的下级代理,不是登录在线人数。 - 新成交购水订单按客户成交时直接归属代理计提;默认一级10%、二级5%、三级2%,可在后台“代理商管理 → 佣金规则”修改,上级不叠加领取。佣金以整数分四舍五入,保存等级、比例和企业归属快照;修改比例不重算旧订单。当前只有待结算账本;结算周期和退款扣回规则待确定,提现关闭。 - 上线前执行 `php scripts/migrate_water_commission.php --apply` 创建 InnoDB 佣金表与平台比例设置;迁移不回填旧订单,重复运行保留已修改的比例。计提随收款订单在同一数据库事务内提交或回滚。保存比例需 `water:agents:write` 权限,并用 `revision` 防止覆盖其他操作员的修改。 - `GET /core/water/agents/commission-policy` 读取三级比例(字段为整数基点,1000 代表 10%)和版本号;`POST` 同路径提交三个 `level{1,2,3}_basis_points` 及 `revision`。比例允许 0% 到 100%,精确到 0.01%;保存会记录操作员与修改前后值。 - 统计与排名不随分页和筛选变化。 ## 层级与账号 `scripts/migrate_water_agent_hierarchy.php --apply` 仅添加可空 `sa_water_agent.parent_id` 及索引,可重复执行。NULL为未设置、0为一级、其他值为上级代理ID;不从旧部门或地区推断供水代理等级。 `AgentHierarchyPolicy` 限制最多三级,阻止自指、循环、缺失上级、把完整子树移动到第四级、给未设置等级/停用代理新增下级。有下级时不能把自身等级清空。事务锁定代理关系后保存,避免并发修改成环。 授权状态由 `AgentAccessPolicy` 根据真实账号及启用的供水角色权限计算: - 已授权:档案启用、关联账号存在且启用,并有启用角色关联的供水权限。 - 待授权:档案启用但未开账号,或账号没有有效供水权限。不是虚构的审核工作流。 - 已停用:合作停用,或已关联账号停用/删除。 开通账号使用独立输入的账号和密码,密码哈希存储;无默认密码、不自动分配角色、部门或超级管理员标记。账号和档案在同一事务创建,失败不留下孤立档案。重复账号或重复开通被拒绝。日志不记录密码,开通控制器返回脱敏失败响应。 供水控制器每次请求核验关联代理合作状态,停用立即阻断关联账号的供水接口;不会修改原系统角色、旧系统账号状态或其非供水权限。菜单可能待客户端刷新后更新;不声称停用自动清除所有旧菜单。 当前页面是平台管理入口;地图辖区和团队关系是业务归属,不会自动转换成数据权限。独立代理业务门户和逐代理数据隔离尚未启用,不应给待开通代理直接分配平台全量管理角色。角色和账号管理仍使用框架原流程。 ## 验证 ### 2026-09-16 排行测试数据 - 执行 `php -d extension=mbstring scripts/seed_water_agent_ranking_demo.php --apply --http`,固定批次 `TEST-WATER-AGENT-RANKING-20260916`;首次执行限当天,复跑只读已有结果,不重复入账或改写用户后续操作。 - 复用已有 `【代理测试0916】` 的5家启用客户,新增订单32–36:李策划2000元(2单)、西瓜商贸1500元(2单)、测试商贸600元(1单),合计4100元、205桶模拟权益。订单凭据、套餐名称及流水均标记为测试,没有实际收款。 - 经 `WaterBusiness::purchase` 生成订单和权益;新测试SKU15及5个套餐完成后停用,保留历史统计。没有入库或创建配送任务;已有代理、客户、订单、账户、库存、设备及流水原记录快照不变。 - PHP语法检查、事务内金额/权益增量及旧记录验证、本地HTTP排行核验通过;再次执行返回 `replayed=true`,排行仍为2000/1500/600元。仅为本月测试数据,下月不会自动续造。 - 增量迁移已执行两次,无旧档案内容回填或账号权限修改。 - `php -d extension=mbstring tests/water_agent_dashboard_test.php --http`:63项通过,含层级规则、筛选分页、订单日期、真实权限状态、账号事务、密码哈希/隐藏、接口即时停用及本地HTTP读取;所有夹具回滚,未单独做并发压力测试。 - 原企业68项(含HTTP)、供水业务69项检查通过,共200项。 - 前端 vue-tsc、ESLint、Stylelint 和 Vite 生产构建通过,`saiadmin-artd/dist` 已更新。 - 浏览器工具仍返回 `unsupported Codex auth method: apikey`,无法完成截图级视觉和真实浏览器交互验收。