input('start_date')); $endDate = Carbon::parse($request->input('end_date')); $projections = $this->projectionGeneratorService->generateProjections( $scenario, $startDate, $endDate ); return new ProjectionResource($projections); } /** * All amounts in cents. Frontend handles conversion to display units. */ public function preview(PreviewAllocationRequest $request, Scenario $scenario): JsonResponse { $amountInCents = (int) $request->input('amount'); $draws = $this->pipelineAllocationService->allocateInflow($scenario, $amountInCents); /** @var array $bucketLookup */ $bucketLookup = $scenario->buckets->keyBy('id')->all(); $allocations = $draws->map(function ($draw) use ($bucketLookup) { $bucket = $bucketLookup[$draw->bucket_id]; return [ 'bucket_id' => $bucket->uuid, 'bucket_name' => $bucket->name, 'bucket_type' => $bucket->type->value, 'allocated_amount' => $draw->amount, 'remaining_capacity' => $bucket->hasFiniteCapacity() ? max(0, $bucket->getEffectiveCapacity() - $draw->amount) : null, ]; })->values(); $totalAllocated = $draws->sum('amount'); return response()->json([ 'allocations' => $allocations, 'total_allocated' => $totalAllocated, 'unallocated' => $amountInCents - $totalAllocated, ]); } /** * Apply an income distribution to bucket balances. * * Re-runs the allocation server-side and updates starting_amount for each bucket. * All amounts in cents. */ public function apply(PreviewAllocationRequest $request, Scenario $scenario): JsonResponse { $amountInCents = (int) $request->input('amount'); $result = $this->applyDistributionAction->execute($scenario, $amountInCents); return response()->json($result); } }