toDateString(); $assignment = AgentFlowCommissionAssignment::query() ->where('agent_id', $agent->id) ->where('effective_from', '<=', $day) ->orderByDesc('effective_from')->orderByDesc('id')->first(); if (!$assignment) { throw new \RuntimeException("代理 {$agent->id} 缺少 {$day} 可用的流水佣金方案历史"); } return $assignment; } public function assign( Agent $agent, AgentFlowCommissionProfile $profile, string $effectiveFrom, ?int $createdBy = null ): AgentFlowCommissionAssignment { $this->assignMany([(int)$agent->id], $profile, $effectiveFrom, $createdBy); return AgentFlowCommissionAssignment::query() ->where('agent_id', $agent->id) ->where('effective_from', Carbon::parse($effectiveFrom)->toDateString()) ->firstOrFail(); } public function assignMany( array $agentIds, AgentFlowCommissionProfile $profile, string $effectiveFrom, ?int $createdBy = null ): void { $agentIds = array_values(array_unique(array_filter(array_map('intval', $agentIds)))); if ($agentIds === []) return; $day = Carbon::parse($effectiveFrom)->toDateString(); $values = array_merge($profile->rateSnapshot(), [ 'flow_commission_profile_id' => (int)$profile->id, 'profile_name' => (string)$profile->name, 'created_by' => $createdBy, ]); DB::transaction(function () use ($agentIds, $day, $values) { $this->assertMutable($agentIds, $day); foreach (array_chunk($agentIds, 500) as $chunk) { foreach ($chunk as $agentId) { AgentFlowCommissionAssignment::query()->updateOrCreate( ['agent_id' => $agentId, 'effective_from' => $day], $values ); } } }); } private function assertMutable(array $agentIds, string $day): void { $newCredited = AgentRebateRecord::query()->whereIn('agent_id', $agentIds) ->where('settlement_date', '>=', $day) ->lockForUpdate() ->pluck('flow_status') ->contains(AgentRebateRecord::STATUS_CREDITED); $legacyCredited = AgentCommission::query()->whereIn('agent_id', $agentIds) ->where('type', 'flow') ->where('settlement_date', '>=', $day) ->lockForUpdate() ->pluck('status') ->contains(AgentRebateRecord::STATUS_CREDITED); if ($newCredited || $legacyCredited) { throw new \RuntimeException('生效日期已有流水佣金入账,不能修改比例方案'); } } }