diff --git a/app/Services/Projection/PipelineAllocationService.php b/app/Services/Projection/PipelineAllocationService.php index 66b4cf9..8540bf2 100644 --- a/app/Services/Projection/PipelineAllocationService.php +++ b/app/Services/Projection/PipelineAllocationService.php @@ -81,7 +81,7 @@ private function calculateBucketAllocation(Bucket $bucket, int $remainingAmount) */ private function calculateFixedAllocation(Bucket $bucket, int $remainingAmount): int { - $bucketCapacity = (int) ($bucket->allocation_value ?? 0); + $bucketCapacity = (int) round($bucket->getEffectiveCapacity()); $currentBalance = $bucket->getCurrentBalance(); $availableSpace = max(0, $bucketCapacity - $currentBalance); diff --git a/tests/Unit/PipelineAllocationServiceTest.php b/tests/Unit/PipelineAllocationServiceTest.php index 6a89d2a..60a9aef 100644 --- a/tests/Unit/PipelineAllocationServiceTest.php +++ b/tests/Unit/PipelineAllocationServiceTest.php @@ -339,4 +339,74 @@ public function test_percentage_allocation_with_insufficient_remaining_amount() $this->assertEquals(95000, $draws[0]->amount); $this->assertEquals(1000, $draws[1]->amount); // 20% of $50 } + + public function test_fixed_allocation_respects_buffer_multiplier(): void + { + Bucket::factory()->create([ + 'scenario_id' => $this->scenario->id, + 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, + 'allocation_value' => 50000, + 'buffer_multiplier' => 1.0, + 'starting_amount' => 0, + 'priority' => 1, + ]); + + // Effective capacity = 50000 * (1 + 1.0) = 100000 + $draws = $this->service->allocateInflow($this->scenario, 100000); + + $this->assertCount(1, $draws); + $this->assertEquals(100000, $draws[0]->amount); + } + + public function test_fixed_allocation_with_buffer_partially_filled(): void + { + $bucket = Bucket::factory()->create([ + 'scenario_id' => $this->scenario->id, + 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, + 'allocation_value' => 50000, + 'buffer_multiplier' => 1.0, + 'starting_amount' => 30000, + 'priority' => 1, + ]); + + // Effective capacity = 100000, balance = 30000, available = 70000 + $draws = $this->service->allocateInflow($this->scenario, 80000); + + $this->assertCount(1, $draws); + $this->assertEquals(70000, $draws[0]->amount); + } + + public function test_buffer_does_not_affect_percentage_allocation(): void + { + Bucket::factory()->create([ + 'scenario_id' => $this->scenario->id, + 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE, + 'allocation_value' => 25.00, + 'buffer_multiplier' => 1.0, + 'starting_amount' => 0, + 'priority' => 1, + ]); + + $draws = $this->service->allocateInflow($this->scenario, 100000); + + $this->assertCount(1, $draws); + $this->assertEquals(25000, $draws[0]->amount); // 25% of 100000 + } + + public function test_buffer_does_not_affect_unlimited_allocation(): void + { + Bucket::factory()->create([ + 'scenario_id' => $this->scenario->id, + 'allocation_type' => BucketAllocationTypeEnum::UNLIMITED, + 'allocation_value' => null, + 'buffer_multiplier' => 1.0, + 'starting_amount' => 0, + 'priority' => 1, + ]); + + $draws = $this->service->allocateInflow($this->scenario, 100000); + + $this->assertCount(1, $draws); + $this->assertEquals(100000, $draws[0]->amount); + } }