Fix code style issues across 32 files (Pint)

This commit is contained in:
myrmidex 2026-03-19 01:09:47 +01:00
parent 54de5b6cc2
commit 67ab1f5f41
32 changed files with 119 additions and 131 deletions

View file

@ -33,7 +33,7 @@ public function execute(
} else { } else {
// Validate priority is positive // Validate priority is positive
if ($priority < 1) { if ($priority < 1) {
throw new InvalidArgumentException("Priority must be at least 1"); throw new InvalidArgumentException('Priority must be at least 1');
} }
// Check if priority already exists and shift others if needed // Check if priority already exists and shift others if needed
@ -57,7 +57,6 @@ public function execute(
}); });
} }
/** /**
* Validate allocation value based on allocation type. * Validate allocation value based on allocation type.
*/ */

View file

@ -36,6 +36,7 @@ public static function labels(): array
foreach (self::cases() as $case) { foreach (self::cases() as $case) {
$labels[$case->value] = $case->label(); $labels[$case->value] = $case->label();
} }
return $labels; return $labels;
} }

View file

@ -34,7 +34,7 @@ public function index(Scenario $scenario): JsonResponse
}); });
return response()->json([ return response()->json([
'buckets' => $buckets 'buckets' => $buckets,
]); ]);
} }
@ -52,7 +52,7 @@ public function store(Request $request, Scenario $scenario): JsonResponse
]); ]);
try { try {
$createBucketAction = new CreateBucketAction(); $createBucketAction = new CreateBucketAction;
$bucket = $createBucketAction->execute( $bucket = $createBucketAction->execute(
$scenario, $scenario,
$validated['name'], $validated['name'],
@ -63,12 +63,12 @@ public function store(Request $request, Scenario $scenario): JsonResponse
return response()->json([ return response()->json([
'bucket' => $this->formatBucketResponse($bucket), 'bucket' => $this->formatBucketResponse($bucket),
'message' => 'Bucket created successfully.' 'message' => 'Bucket created successfully.',
], 201); ], 201);
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
return response()->json([ return response()->json([
'message' => 'Validation failed.', 'message' => 'Validation failed.',
'errors' => ['allocation_value' => [$e->getMessage()]] 'errors' => ['allocation_value' => [$e->getMessage()]],
], 422); ], 422);
} }
} }
@ -107,7 +107,7 @@ public function update(Request $request, Bucket $bucket): JsonResponse
return response()->json([ return response()->json([
'bucket' => $this->formatBucketResponse($bucket), 'bucket' => $this->formatBucketResponse($bucket),
'message' => 'Bucket updated successfully.' 'message' => 'Bucket updated successfully.',
]); ]);
} }
@ -125,7 +125,7 @@ public function destroy(Bucket $bucket): JsonResponse
$this->shiftPrioritiesDown($scenarioId, $deletedPriority); $this->shiftPrioritiesDown($scenarioId, $deletedPriority);
return response()->json([ return response()->json([
'message' => 'Bucket deleted successfully.' 'message' => 'Bucket deleted successfully.',
]); ]);
} }
@ -151,7 +151,7 @@ public function updatePriorities(Request $request, Scenario $scenario): JsonResp
} }
return response()->json([ return response()->json([
'message' => 'Bucket priorities updated successfully.' 'message' => 'Bucket priorities updated successfully.',
]); ]);
} }
@ -175,7 +175,6 @@ private function formatBucketResponse(Bucket $bucket): array
]; ];
} }
/** /**
* Shift priorities down to fill gap after deletion. * Shift priorities down to fill gap after deletion.
*/ */

View file

@ -3,16 +3,16 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Actions\CreateScenarioAction; use App\Actions\CreateScenarioAction;
use App\Actions\UpdateScenarioAction;
use App\Actions\DeleteScenarioAction; use App\Actions\DeleteScenarioAction;
use App\Http\Resources\BucketResource; use App\Actions\UpdateScenarioAction;
use App\Http\Resources\StreamResource;
use App\Http\Resources\ScenarioResource;
use App\Http\Requests\StoreScenarioRequest; use App\Http\Requests\StoreScenarioRequest;
use App\Http\Requests\UpdateScenarioRequest; use App\Http\Requests\UpdateScenarioRequest;
use App\Http\Resources\BucketResource;
use App\Http\Resources\ScenarioResource;
use App\Http\Resources\StreamResource;
use App\Models\Scenario; use App\Models\Scenario;
use App\Repositories\StreamRepository;
use App\Repositories\ScenarioRepository; use App\Repositories\ScenarioRepository;
use App\Repositories\StreamRepository;
use App\Services\Streams\StatsService; use App\Services\Streams\StatsService;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Inertia\Inertia; use Inertia\Inertia;
@ -32,7 +32,7 @@ public function __construct(
public function index(): Response public function index(): Response
{ {
return Inertia::render('Scenarios/Index', [ return Inertia::render('Scenarios/Index', [
'scenarios' => ScenarioResource::collection($this->scenarioRepository->getAll()) 'scenarios' => ScenarioResource::collection($this->scenarioRepository->getAll()),
]); ]);
} }
@ -46,7 +46,7 @@ public function show(Scenario $scenario): Response
'scenario' => new ScenarioResource($scenario), 'scenario' => new ScenarioResource($scenario),
'buckets' => BucketResource::collection($scenario->buckets), 'buckets' => BucketResource::collection($scenario->buckets),
'streams' => StreamResource::collection($this->streamRepository->getForScenario($scenario)), 'streams' => StreamResource::collection($this->streamRepository->getForScenario($scenario)),
'streamStats' => $this->statsService->getSummaryStats($scenario) 'streamStats' => $this->statsService->getSummaryStats($scenario),
]); ]);
} }
@ -65,7 +65,7 @@ public function store(StoreScenarioRequest $request): RedirectResponse
public function edit(Scenario $scenario): Response public function edit(Scenario $scenario): Response
{ {
return Inertia::render('Scenarios/Edit', [ return Inertia::render('Scenarios/Edit', [
'scenario' => new ScenarioResource($scenario) 'scenario' => new ScenarioResource($scenario),
]); ]);
} }

View file

@ -4,11 +4,11 @@
use App\Http\Requests\StoreStreamRequest; use App\Http\Requests\StoreStreamRequest;
use App\Http\Requests\UpdateStreamRequest; use App\Http\Requests\UpdateStreamRequest;
use App\Models\Stream; use App\Http\Resources\StreamResource;
use App\Models\Scenario; use App\Models\Scenario;
use App\Models\Stream;
use App\Repositories\StreamRepository; use App\Repositories\StreamRepository;
use App\Services\Streams\StatsService; use App\Services\Streams\StatsService;
use App\Http\Resources\StreamResource;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
class StreamController extends Controller class StreamController extends Controller
@ -24,7 +24,7 @@ public function index(Scenario $scenario): JsonResponse
return response()->json([ return response()->json([
'streams' => StreamResource::collection($streams), 'streams' => StreamResource::collection($streams),
'stats' => $this->statsService->getSummaryStats($scenario) 'stats' => $this->statsService->getSummaryStats($scenario),
]); ]);
} }
@ -34,7 +34,7 @@ public function store(StoreStreamRequest $request, Scenario $scenario): JsonResp
return response()->json([ return response()->json([
'stream' => new StreamResource($stream), 'stream' => new StreamResource($stream),
'message' => 'Stream created successfully.' 'message' => 'Stream created successfully.',
], 201); ], 201);
} }
@ -44,7 +44,7 @@ public function update(UpdateStreamRequest $request, Stream $stream): JsonRespon
return response()->json([ return response()->json([
'stream' => new StreamResource($stream), 'stream' => new StreamResource($stream),
'message' => 'Stream updated successfully.' 'message' => 'Stream updated successfully.',
]); ]);
} }
@ -53,7 +53,7 @@ public function destroy(Stream $stream): JsonResponse
$this->streamRepository->delete($stream); $this->streamRepository->delete($stream);
return response()->json([ return response()->json([
'message' => 'Stream deleted successfully.' 'message' => 'Stream deleted successfully.',
]); ]);
} }
@ -63,7 +63,7 @@ public function toggle(Stream $stream): JsonResponse
return response()->json([ return response()->json([
'stream' => new StreamResource($stream), 'stream' => new StreamResource($stream),
'message' => $stream->is_active ? 'Stream activated.' : 'Stream deactivated.' 'message' => $stream->is_active ? 'Stream activated.' : 'Stream deactivated.',
]); ]);
} }
} }

View file

@ -2,8 +2,8 @@
namespace App\Http\Requests; namespace App\Http\Requests;
use App\Models\Stream;
use App\Models\Scenario; use App\Models\Scenario;
use App\Models\Stream;
use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
@ -37,7 +37,7 @@ public function rules(): array
Stream::FREQUENCY_MONTHLY, Stream::FREQUENCY_MONTHLY,
Stream::FREQUENCY_QUARTERLY, Stream::FREQUENCY_QUARTERLY,
Stream::FREQUENCY_YEARLY, Stream::FREQUENCY_YEARLY,
]) ]),
], ],
'start_date' => ['required', 'date', 'date_format:Y-m-d'], 'start_date' => ['required', 'date', 'date_format:Y-m-d'],
'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'], 'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'],

View file

@ -3,7 +3,6 @@
namespace App\Http\Requests; namespace App\Http\Requests;
use App\Models\Stream; use App\Models\Stream;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
@ -31,7 +30,7 @@ public function rules(): array
Stream::FREQUENCY_MONTHLY, Stream::FREQUENCY_MONTHLY,
Stream::FREQUENCY_QUARTERLY, Stream::FREQUENCY_QUARTERLY,
Stream::FREQUENCY_YEARLY, Stream::FREQUENCY_YEARLY,
]) ]),
], ],
'start_date' => ['required', 'date', 'date_format:Y-m-d'], 'start_date' => ['required', 'date', 'date_format:Y-m-d'],
'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'], 'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'],

View file

@ -17,14 +17,16 @@
* @property Carbon $date * @property Carbon $date
* @property string $description * @property string $description
* @property bool $is_projected * @property bool $is_projected
*
* @method static create(array $array) * @method static create(array $array)
*/ */
class Draw extends Model class Draw extends Model
{ {
use HasAmount;
/** @use HasFactory<DrawFactory> */ /** @use HasFactory<DrawFactory> */
use HasFactory; use HasFactory;
use HasProjectionStatus; use HasProjectionStatus;
use HasAmount;
protected $fillable = [ protected $fillable = [
'bucket_id', 'bucket_id',

View file

@ -19,8 +19,8 @@
*/ */
class Inflow extends Model class Inflow extends Model
{ {
use HasProjectionStatus;
use HasAmount; use HasAmount;
use HasProjectionStatus;
protected $fillable = [ protected $fillable = [
'stream_id', 'stream_id',

View file

@ -18,14 +18,16 @@
* @property Carbon $date * @property Carbon $date
* @property string $description * @property string $description
* @property bool $is_projected * @property bool $is_projected
*
* @method static create(array $array) * @method static create(array $array)
*/ */
class Outflow extends Model class Outflow extends Model
{ {
use HasAmount;
/** @use HasFactory<OutflowFactory> */ /** @use HasFactory<OutflowFactory> */
use HasFactory; use HasFactory;
use HasProjectionStatus; use HasProjectionStatus;
use HasAmount;
protected $fillable = [ protected $fillable = [
'stream_id', 'stream_id',

View file

@ -11,6 +11,7 @@
/** /**
* @property int $id * @property int $id
* @property Collection<Bucket> $buckets * @property Collection<Bucket> $buckets
*
* @method static create(array $data) * @method static create(array $data)
*/ */
class Scenario extends Model class Scenario extends Model

View file

@ -17,7 +17,7 @@
*/ */
class Stream extends Model class Stream extends Model
{ {
use HasFactory, HasAmount; use HasAmount, HasFactory;
protected $fillable = [ protected $fillable = [
'scenario_id', 'scenario_id',
@ -76,6 +76,7 @@ public function getMonthlyEquivalent(): float
if (! $this->frequency) { if (! $this->frequency) {
return 0; return 0;
} }
return $this->amount * $this->frequency->getMonthlyEquivalentMultiplier(); return $this->amount * $this->frequency->getMonthlyEquivalentMultiplier();
} }

View file

@ -2,8 +2,8 @@
namespace App\Repositories; namespace App\Repositories;
use App\Models\Stream;
use App\Models\Scenario; use App\Models\Scenario;
use App\Models\Stream;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
class StreamRepository class StreamRepository
@ -37,7 +37,7 @@ public function delete(Stream $stream): bool
public function toggleActive(Stream $stream): Stream public function toggleActive(Stream $stream): Stream
{ {
$stream->update([ $stream->update([
'is_active' => !$stream->is_active 'is_active' => ! $stream->is_active,
]); ]);
return $stream->fresh('bucket'); return $stream->fresh('bucket');
@ -57,8 +57,6 @@ public function bucketBelongsToScenario(Scenario $scenario, ?int $bucketId): boo
->exists(); ->exists();
} }
/** /**
* Get streams grouped by type * Get streams grouped by type
*/ */

View file

@ -14,10 +14,6 @@
/** /**
* Allocate an inflow amount across scenario buckets according to priority rules. * Allocate an inflow amount across scenario buckets according to priority rules.
* *
* @param Scenario $scenario
* @param int $amount
* @param Carbon|null $date
* @param string|null $description
* @return Collection<Draw> Collection of Draw models * @return Collection<Draw> Collection of Draw models
*/ */
public function allocateInflow(Scenario $scenario, int $amount, ?Carbon $date = null, ?string $description = null): Collection public function allocateInflow(Scenario $scenario, int $amount, ?Carbon $date = null, ?string $description = null): Collection
@ -54,7 +50,7 @@ public function allocateInflow(Scenario $scenario, int $amount, ?Carbon $date =
'bucket_id' => $bucket->id, 'bucket_id' => $bucket->id,
'amount' => $allocation, 'amount' => $allocation,
'date' => $allocationDate, 'date' => $allocationDate,
'description' => $description ?? "Allocation from inflow", 'description' => $description ?? 'Allocation from inflow',
'is_projected' => true, 'is_projected' => true,
]); ]);
@ -69,10 +65,6 @@ public function allocateInflow(Scenario $scenario, int $amount, ?Carbon $date =
/** /**
* Calculate how much should be allocated to a specific bucket. * Calculate how much should be allocated to a specific bucket.
*
* @param Bucket $bucket
* @param int $remainingAmount
* @return int
*/ */
private function calculateBucketAllocation(Bucket $bucket, int $remainingAmount): int private function calculateBucketAllocation(Bucket $bucket, int $remainingAmount): int
{ {
@ -86,10 +78,6 @@ private function calculateBucketAllocation(Bucket $bucket, int $remainingAmount)
/** /**
* Calculate allocation for fixed limit buckets. * Calculate allocation for fixed limit buckets.
*
* @param Bucket $bucket
* @param int $remainingAmount
* @return int
*/ */
private function calculateFixedAllocation(Bucket $bucket, int $remainingAmount): int private function calculateFixedAllocation(Bucket $bucket, int $remainingAmount): int
{ {
@ -102,14 +90,11 @@ private function calculateFixedAllocation(Bucket $bucket, int $remainingAmount):
/** /**
* Calculate allocation for percentage buckets. * Calculate allocation for percentage buckets.
*
* @param Bucket $bucket
* @param int $remainingAmount
* @return int
*/ */
private function calculatePercentageAllocation(Bucket $bucket, int $remainingAmount): int private function calculatePercentageAllocation(Bucket $bucket, int $remainingAmount): int
{ {
$percentage = $bucket->allocation_value ?? 0; $percentage = $bucket->allocation_value ?? 0;
return (int) round($remainingAmount * ($percentage / 100)); return (int) round($remainingAmount * ($percentage / 100));
} }
} }

View file

@ -6,7 +6,6 @@
use App\Http\Controllers\StreamController; use App\Http\Controllers\StreamController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Inertia\Inertia; use Inertia\Inertia;
use Laravel\Fortify\Features;
// Scenario routes (no auth required for MVP) // Scenario routes (no auth required for MVP)
Route::get('/', [ScenarioController::class, 'index'])->name('scenarios.index'); Route::get('/', [ScenarioController::class, 'index'])->name('scenarios.index');

View file

@ -15,12 +15,13 @@ class CreateBucketActionTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
private CreateBucketAction $action; private CreateBucketAction $action;
private Scenario $scenario; private Scenario $scenario;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->action = new CreateBucketAction(); $this->action = new CreateBucketAction;
$this->scenario = Scenario::factory()->create(); $this->scenario = Scenario::factory()->create();
} }
@ -135,7 +136,6 @@ public function test_existing_priorities_are_shifted_when_inserting(): void
$this->assertEquals(4, $bucket3->priority); // Shifted from 3 to 4 $this->assertEquals(4, $bucket3->priority); // Shifted from 3 to 4
} }
public function test_throws_exception_for_fixed_limit_without_allocation_value(): void public function test_throws_exception_for_fixed_limit_without_allocation_value(): void
{ {
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);

View file

@ -14,12 +14,13 @@ class PipelineAllocationServiceTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
private PipelineAllocationService $service; private PipelineAllocationService $service;
private Scenario $scenario; private Scenario $scenario;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->service = new PipelineAllocationService(); $this->service = new PipelineAllocationService;
$this->scenario = Scenario::factory()->create(); $this->scenario = Scenario::factory()->create();
} }
@ -32,7 +33,7 @@ public function test_allocates_to_single_fixed_bucket()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 50000, 'allocation_value' => 50000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
// Act: Allocate $300 // Act: Allocate $300
@ -52,21 +53,21 @@ public function test_allocates_across_multiple_fixed_buckets_by_priority()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 20000, 'allocation_value' => 20000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$bucket2 = Bucket::factory()->create([ $bucket2 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 30000, 'allocation_value' => 30000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
$bucket3 = Bucket::factory()->create([ $bucket3 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 15000, 'allocation_value' => 15000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 3 'priority' => 3,
]); ]);
// Act: Allocate $550 (should fill bucket1 + bucket2 + partial bucket3) // Act: Allocate $550 (should fill bucket1 + bucket2 + partial bucket3)
@ -96,14 +97,14 @@ public function test_percentage_bucket_gets_percentage_of_remaining_amount()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 30000, 'allocation_value' => 30000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$percentageBucket = Bucket::factory()->create([ $percentageBucket = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE, 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE,
'allocation_value' => 20.00, // 20% 'allocation_value' => 20.00, // 20%
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
// Act: Allocate $1000 // Act: Allocate $1000
@ -123,14 +124,14 @@ public function test_unlimited_bucket_gets_all_remaining_amount()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 50000, 'allocation_value' => 50000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$unlimitedBucket = Bucket::factory()->create([ $unlimitedBucket = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::UNLIMITED, 'allocation_type' => BucketAllocationTypeEnum::UNLIMITED,
'allocation_value' => null, 'allocation_value' => null,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
// Act: Allocate $1500 // Act: Allocate $1500
@ -150,14 +151,14 @@ public function test_skips_buckets_with_zero_allocation()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 0, // No capacity 'allocation_value' => 0, // No capacity
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$normalBucket = Bucket::factory()->create([ $normalBucket = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 30000, 'allocation_value' => 30000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
// Act: Allocate $200 // Act: Allocate $200
@ -177,35 +178,35 @@ public function test_handles_complex_mixed_bucket_scenario()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 100000, 'allocation_value' => 100000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$percentage1 = Bucket::factory()->create([ $percentage1 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE, 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE,
'allocation_value' => 15.00, // 15% 'allocation_value' => 15.00, // 15%
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
$fixed2 = Bucket::factory()->create([ $fixed2 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 50000, 'allocation_value' => 50000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 3 'priority' => 3,
]); ]);
$percentage2 = Bucket::factory()->create([ $percentage2 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE, 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE,
'allocation_value' => 25.00, // 25% 'allocation_value' => 25.00, // 25%
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 4 'priority' => 4,
]); ]);
$unlimited = Bucket::factory()->create([ $unlimited = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::UNLIMITED, 'allocation_type' => BucketAllocationTypeEnum::UNLIMITED,
'allocation_value' => null, 'allocation_value' => null,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 5 'priority' => 5,
]); ]);
// Act: Allocate $5000 // Act: Allocate $5000
@ -248,7 +249,7 @@ public function test_returns_empty_array_when_amount_is_zero()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 50000, 'allocation_value' => 50000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
// Act: Allocate $0 // Act: Allocate $0
@ -266,7 +267,7 @@ public function test_handles_negative_amount_gracefully()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 50000, 'allocation_value' => 50000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
// Act: Allocate negative amount // Act: Allocate negative amount
@ -284,21 +285,21 @@ public function test_respects_bucket_priority_order()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 10000, 'allocation_value' => 10000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 10 // Higher number 'priority' => 10, // Higher number
]); ]);
$bucket1 = Bucket::factory()->create([ $bucket1 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 20000, 'allocation_value' => 20000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 // Lower number (higher priority) 'priority' => 1, // Lower number (higher priority)
]); ]);
$bucket2 = Bucket::factory()->create([ $bucket2 = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 15000, 'allocation_value' => 15000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 5 // Middle 'priority' => 5, // Middle
]); ]);
// Act: Allocate $250 // Act: Allocate $250
@ -320,14 +321,14 @@ public function test_percentage_allocation_with_insufficient_remaining_amount()
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
'allocation_value' => 95000, 'allocation_value' => 95000,
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 1 'priority' => 1,
]); ]);
$percentageBucket = Bucket::factory()->create([ $percentageBucket = Bucket::factory()->create([
'scenario_id' => $this->scenario->id, 'scenario_id' => $this->scenario->id,
'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE, 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE,
'allocation_value' => 20.00, // 20% 'allocation_value' => 20.00, // 20%
'starting_amount' => 0, 'starting_amount' => 0,
'priority' => 2 'priority' => 2,
]); ]);
// Act: Allocate $1000 (only $50 left after fixed) // Act: Allocate $1000 (only $50 left after fixed)

View file

@ -19,12 +19,13 @@ class ProjectionGeneratorServiceTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
private ProjectionGeneratorService $service; private ProjectionGeneratorService $service;
private Scenario $scenario; private Scenario $scenario;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->service = new ProjectionGeneratorService(new PipelineAllocationService()); $this->service = new ProjectionGeneratorService(new PipelineAllocationService);
$this->scenario = Scenario::factory()->create(); $this->scenario = Scenario::factory()->create();
// Set a fixed "now" for consistent testing // Set a fixed "now" for consistent testing