Collection of Draw models */ public function allocateInflow(Scenario $scenario, float $amount, ?Carbon $date = null, ?string $description = null): Collection { $draws = collect(); // Guard clauses if ($amount <= 0) { return $draws; } // Get buckets ordered by priority $buckets = $scenario->buckets() ->orderBy('priority') ->get(); if ($buckets->isEmpty()) { return $draws; } $priorityOrder = 1; $remainingAmount = $amount; $allocationDate = $date ?? now(); foreach ($buckets as $bucket) { if ($remainingAmount <= 0) { break; } $allocation = $this->calculateBucketAllocation($bucket, $remainingAmount); if ($allocation > 0) { $draw = new Draw([ 'bucket_id' => $bucket->id, 'amount' => $allocation, 'date' => $allocationDate, 'description' => $description ?? "Allocation from inflow", 'is_projected' => true, ]); // Add priority_order as a custom attribute for pipeline visualization $draw->priority_order = $priorityOrder; $draws->push($draw); $remainingAmount -= $allocation; $priorityOrder++; } } return $draws; } /** * Calculate how much should be allocated to a specific bucket. * * @param Bucket $bucket * @param float $remainingAmount * @return float */ private function calculateBucketAllocation(Bucket $bucket, float $remainingAmount): float { return match ($bucket->allocation_type) { BucketAllocationType::FIXED_LIMIT => $this->calculateFixedAllocation($bucket, $remainingAmount), BucketAllocationType::PERCENTAGE => $this->calculatePercentageAllocation($bucket, $remainingAmount), BucketAllocationType::UNLIMITED => $remainingAmount, // Takes all remaining default => 0, }; } /** * Calculate allocation for fixed limit buckets. * * @param Bucket $bucket * @param float $remainingAmount * @return float */ private function calculateFixedAllocation(Bucket $bucket, float $remainingAmount): float { $bucketCapacity = $bucket->allocation_value ?? 0; $currentBalance = $bucket->getCurrentBalance(); $availableSpace = max(0, $bucketCapacity - $currentBalance); return min($availableSpace, $remainingAmount); } /** * Calculate allocation for percentage buckets. * * @param Bucket $bucket * @param float $remainingAmount * @return float */ private function calculatePercentageAllocation(Bucket $bucket, float $remainingAmount): float { $percentage = $bucket->allocation_value ?? 0; return $remainingAmount * ($percentage / 100); } }