| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- <?php
- declare(strict_types=1);
- namespace plugin\saiadmin\app\service\agent;
- use DomainException;
- use plugin\saiadmin\app\model\water\WaterAgent;
- use plugin\saiadmin\app\model\water\WaterCommission;
- use plugin\saiadmin\app\model\water\WaterEnterprise;
- use plugin\saiadmin\app\model\water\WaterOrder;
- /** Record the direct agent's commission inside the paid-order transaction. */
- final class WaterCommissionAccrual
- {
- public function record(WaterOrder $order, WaterEnterprise $enterprise): void
- {
- // Historical demo orders are not real receipts and must not create payable commissions.
- if (str_starts_with($order->reference, 'TEST-') || str_contains($order->package_name, '测试')) {
- return;
- }
- $agent = $enterprise->agent;
- if (!$agent || (int) $agent->status !== 1) {
- return;
- }
- $level = $this->level($agent);
- if ($level === null) {
- return;
- }
- $baseAmount = (int) $order->amount_cents;
- $rate = WaterCommissionPolicy::rate($level, true);
- WaterCommission::query()->create([
- 'order_id' => (int) $order->id,
- 'enterprise_id' => (int) $enterprise->id,
- 'enterprise_name' => $enterprise->name,
- 'agent_id' => (int) $agent->id,
- 'agent_level' => $level,
- 'rate_basis_points' => $rate,
- 'base_amount_cents' => $baseAmount,
- 'amount_cents' => WaterCommissionPolicy::amountAtRate($baseAmount, $rate),
- 'status' => 'pending',
- 'created_at' => $order->created_at,
- ]);
- }
- private function level(WaterAgent $agent): ?int
- {
- $level = 1;
- $seen = [];
- while (true) {
- $id = (int) $agent->id;
- if (isset($seen[$id]) || $level > 3) {
- throw new DomainException('代理上下级关系异常,无法计提佣金');
- }
- $seen[$id] = true;
- if ($agent->parent_id === null) {
- return null;
- }
- if ((int) $agent->parent_id === 0) {
- return $level;
- }
- $agent = WaterAgent::query()->find((int) $agent->parent_id)
- ?? throw new DomainException('代理上级不存在,无法计提佣金');
- $level++;
- }
- }
- }
|