16 - Pass raw storage units through API
This commit is contained in:
parent
4554f4e417
commit
3a5126f51c
7 changed files with 40 additions and 28 deletions
|
|
@ -25,8 +25,8 @@ public static function values(): array
|
||||||
public function getAllocationValueRules(): array
|
public function getAllocationValueRules(): array
|
||||||
{
|
{
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::FIXED_LIMIT => ['required', 'numeric', 'min:0'],
|
self::FIXED_LIMIT => ['required', 'integer', 'min:0'],
|
||||||
self::PERCENTAGE => ['required', 'numeric', 'min:0.01', 'max:100'],
|
self::PERCENTAGE => ['required', 'integer', 'min:1', 'max:10000'],
|
||||||
self::UNLIMITED => ['nullable'],
|
self::UNLIMITED => ['nullable'],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public function store(Request $request, Scenario $scenario): JsonResponse
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'type' => 'required|in:'.implode(',', BucketTypeEnum::values()),
|
'type' => 'required|in:'.implode(',', BucketTypeEnum::values()),
|
||||||
'allocation_type' => 'required|in:'.implode(',', BucketAllocationTypeEnum::values()),
|
'allocation_type' => 'required|in:'.implode(',', BucketAllocationTypeEnum::values()),
|
||||||
'allocation_value' => 'nullable|numeric',
|
'allocation_value' => 'nullable|integer',
|
||||||
'buffer_multiplier' => 'sometimes|numeric|min:0',
|
'buffer_multiplier' => 'sometimes|numeric|min:0',
|
||||||
'priority' => 'nullable|integer|min:1',
|
'priority' => 'nullable|integer|min:1',
|
||||||
]);
|
]);
|
||||||
|
|
@ -75,7 +75,7 @@ public function update(Request $request, Bucket $bucket): JsonResponse
|
||||||
'name' => 'sometimes|required|string|max:255',
|
'name' => 'sometimes|required|string|max:255',
|
||||||
'type' => 'sometimes|required|in:'.implode(',', BucketTypeEnum::values()),
|
'type' => 'sometimes|required|in:'.implode(',', BucketTypeEnum::values()),
|
||||||
'allocation_type' => 'sometimes|required|in:'.implode(',', BucketAllocationTypeEnum::values()),
|
'allocation_type' => 'sometimes|required|in:'.implode(',', BucketAllocationTypeEnum::values()),
|
||||||
'allocation_value' => 'sometimes|nullable|numeric',
|
'allocation_value' => 'sometimes|nullable|integer',
|
||||||
'buffer_multiplier' => 'sometimes|numeric|min:0',
|
'buffer_multiplier' => 'sometimes|numeric|min:0',
|
||||||
'starting_amount' => 'sometimes|integer|min:0',
|
'starting_amount' => 'sometimes|integer|min:0',
|
||||||
'priority' => 'sometimes|nullable|integer|min:1',
|
'priority' => 'sometimes|nullable|integer|min:1',
|
||||||
|
|
@ -221,6 +221,8 @@ private function validateBucketTypeConstraints(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format bucket data for JSON response.
|
* Format bucket data for JSON response.
|
||||||
|
* All amounts in storage units (cents for currency, basis points for percentages).
|
||||||
|
* Frontend handles conversion to display units.
|
||||||
*/
|
*/
|
||||||
private function formatBucketResponse(Bucket $bucket): array
|
private function formatBucketResponse(Bucket $bucket): array
|
||||||
{
|
{
|
||||||
|
|
@ -235,11 +237,11 @@ private function formatBucketResponse(Bucket $bucket): array
|
||||||
'allocation_value' => $bucket->allocation_value,
|
'allocation_value' => $bucket->allocation_value,
|
||||||
'allocation_type_label' => $bucket->getAllocationTypeLabel(),
|
'allocation_type_label' => $bucket->getAllocationTypeLabel(),
|
||||||
'buffer_multiplier' => (float) $bucket->buffer_multiplier,
|
'buffer_multiplier' => (float) $bucket->buffer_multiplier,
|
||||||
'effective_capacity' => $bucket->getEffectiveCapacity(),
|
'effective_capacity' => $bucket->hasFiniteCapacity() ? $bucket->getEffectiveCapacity() : null,
|
||||||
'starting_amount' => $bucket->starting_amount,
|
'starting_amount' => $bucket->starting_amount,
|
||||||
'current_balance' => $bucket->getCurrentBalance(),
|
'current_balance' => $bucket->getCurrentBalance(),
|
||||||
'has_available_space' => $bucket->hasAvailableSpace(),
|
'has_available_space' => $bucket->hasAvailableSpace(),
|
||||||
'available_space' => $bucket->getAvailableSpace(),
|
'available_space' => $bucket->hasFiniteCapacity() ? $bucket->getAvailableSpace() : null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,12 @@ public function calculate(CalculateProjectionRequest $request, Scenario $scenari
|
||||||
return new ProjectionResource($projections);
|
return new ProjectionResource($projections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All amounts in cents. Frontend handles conversion to display units.
|
||||||
|
*/
|
||||||
public function preview(PreviewAllocationRequest $request, Scenario $scenario): JsonResponse
|
public function preview(PreviewAllocationRequest $request, Scenario $scenario): JsonResponse
|
||||||
{
|
{
|
||||||
$amountInCents = (int) round($request->input('amount') * 100);
|
$amountInCents = (int) $request->input('amount');
|
||||||
|
|
||||||
$draws = $this->pipelineAllocationService->allocateInflow($scenario, $amountInCents);
|
$draws = $this->pipelineAllocationService->allocateInflow($scenario, $amountInCents);
|
||||||
|
|
||||||
|
|
@ -49,30 +52,19 @@ public function preview(PreviewAllocationRequest $request, Scenario $scenario):
|
||||||
'bucket_id' => $bucket->uuid,
|
'bucket_id' => $bucket->uuid,
|
||||||
'bucket_name' => $bucket->name,
|
'bucket_name' => $bucket->name,
|
||||||
'bucket_type' => $bucket->type->value,
|
'bucket_type' => $bucket->type->value,
|
||||||
'allocated_amount' => (float) $draw->amount_currency,
|
'allocated_amount' => $draw->amount,
|
||||||
'remaining_capacity' => $this->remainingCapacity($bucket, $draw->amount),
|
'remaining_capacity' => $bucket->hasFiniteCapacity()
|
||||||
|
? max(0, $bucket->getEffectiveCapacity() - $draw->amount)
|
||||||
|
: null,
|
||||||
];
|
];
|
||||||
})->values();
|
})->values();
|
||||||
|
|
||||||
$totalAllocatedCents = $draws->sum('amount');
|
$totalAllocated = $draws->sum('amount');
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'allocations' => $allocations,
|
'allocations' => $allocations,
|
||||||
'total_allocated' => (float) round($totalAllocatedCents / 100, 2),
|
'total_allocated' => $totalAllocated,
|
||||||
'unallocated' => (float) round(($amountInCents - $totalAllocatedCents) / 100, 2),
|
'unallocated' => $amountInCents - $totalAllocated,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function remainingCapacity(Bucket $bucket, int $allocatedCents): ?float
|
|
||||||
{
|
|
||||||
$capacityCents = $bucket->getEffectiveCapacity();
|
|
||||||
|
|
||||||
if ($capacityCents === PHP_INT_MAX) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$remainingCents = max(0, $capacityCents - $allocatedCents);
|
|
||||||
|
|
||||||
return round($remainingCents / 100, 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ public function authorize(): bool
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'amount' => ['required', 'numeric', 'min:0.01'],
|
'amount' => ['required', 'integer', 'min:1'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
class BucketResource extends JsonResource
|
class BucketResource extends JsonResource
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* All amounts in storage units (cents for currency, basis points for percentages).
|
||||||
|
* Frontend handles conversion to display units.
|
||||||
|
*/
|
||||||
public function toArray(Request $request): array
|
public function toArray(Request $request): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
@ -20,11 +24,11 @@ public function toArray(Request $request): array
|
||||||
'allocation_value' => $this->allocation_value,
|
'allocation_value' => $this->allocation_value,
|
||||||
'allocation_type_label' => $this->getAllocationTypeLabel(),
|
'allocation_type_label' => $this->getAllocationTypeLabel(),
|
||||||
'buffer_multiplier' => (float) $this->buffer_multiplier,
|
'buffer_multiplier' => (float) $this->buffer_multiplier,
|
||||||
'effective_capacity' => $this->getEffectiveCapacity(),
|
'effective_capacity' => $this->hasFiniteCapacity() ? $this->getEffectiveCapacity() : null,
|
||||||
'starting_amount' => $this->starting_amount,
|
'starting_amount' => $this->starting_amount,
|
||||||
'current_balance' => $this->getCurrentBalance(),
|
'current_balance' => $this->getCurrentBalance(),
|
||||||
'has_available_space' => $this->hasAvailableSpace(),
|
'has_available_space' => $this->hasAvailableSpace(),
|
||||||
'available_space' => $this->getAvailableSpace(),
|
'available_space' => $this->hasFiniteCapacity() ? $this->getAvailableSpace() : null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,14 @@ public function getAvailableSpace(): int
|
||||||
return max(0, $this->getEffectiveCapacity() - $this->getCurrentBalance());
|
return max(0, $this->getEffectiveCapacity() - $this->getCurrentBalance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this bucket has a finite capacity (fixed_limit only).
|
||||||
|
*/
|
||||||
|
public function hasFiniteCapacity(): bool
|
||||||
|
{
|
||||||
|
return $this->allocation_type === BucketAllocationTypeEnum::FIXED_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get display label for allocation type.
|
* Get display label for allocation type.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,12 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: app/Http/Resources/BucketResource.php
|
path: app/Http/Resources/BucketResource.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: '#^Call to an undefined method App\\Http\\Resources\\BucketResource\:\:hasFiniteCapacity\(\)\.$#'
|
||||||
|
identifier: method.notFound
|
||||||
|
count: 2
|
||||||
|
path: app/Http/Resources/BucketResource.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: '#^Access to an undefined property App\\Http\\Resources\\DrawResource\:\:\$amount_currency\.$#'
|
message: '#^Access to an undefined property App\\Http\\Resources\\DrawResource\:\:\$amount_currency\.$#'
|
||||||
identifier: property.notFound
|
identifier: property.notFound
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue