4 - Add BucketTypeEnum and update Bucket model, migration, factory, and resource

This commit is contained in:
myrmidex 2026-03-19 21:14:36 +01:00
parent 72cc6ff0b7
commit fe5355d182
6 changed files with 108 additions and 2 deletions

View file

@ -0,0 +1,24 @@
<?php
namespace App\Enums;
enum BucketTypeEnum: string
{
case NEED = 'need';
case WANT = 'want';
case OVERFLOW = 'overflow';
public function getLabel(): string
{
return match ($this) {
self::NEED => 'Need',
self::WANT => 'Want',
self::OVERFLOW => 'Overflow',
};
}
public static function values(): array
{
return array_column(self::cases(), 'value');
}
}

View file

@ -12,6 +12,8 @@ public function toArray(Request $request): array
return [ return [
'id' => $this->uuid, 'id' => $this->uuid,
'name' => $this->name, 'name' => $this->name,
'type' => $this->type,
'type_label' => $this->type->getLabel(),
'priority' => $this->priority, 'priority' => $this->priority,
'sort_order' => $this->sort_order, 'sort_order' => $this->sort_order,
'allocation_type' => $this->allocation_type, 'allocation_type' => $this->allocation_type,

View file

@ -3,6 +3,7 @@
namespace App\Models; namespace App\Models;
use App\Enums\BucketAllocationTypeEnum; use App\Enums\BucketAllocationTypeEnum;
use App\Enums\BucketTypeEnum;
use App\Models\Traits\HasUuid; use App\Models\Traits\HasUuid;
use Database\Factories\BucketFactory; use Database\Factories\BucketFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
@ -14,6 +15,7 @@
* @property int $id * @property int $id
* @property string $uuid * @property string $uuid
* @property int $scenario_id * @property int $scenario_id
* @property BucketTypeEnum $type
* @property Scenario $scenario * @property Scenario $scenario
* @property string $name * @property string $name
* @property int $priority * @property int $priority
@ -31,6 +33,7 @@ class Bucket extends Model
protected $fillable = [ protected $fillable = [
'scenario_id', 'scenario_id',
'name', 'name',
'type',
'priority', 'priority',
'sort_order', 'sort_order',
'allocation_type', 'allocation_type',
@ -39,6 +42,7 @@ class Bucket extends Model
]; ];
protected $casts = [ protected $casts = [
'type' => BucketTypeEnum::class,
'priority' => 'integer', 'priority' => 'integer',
'sort_order' => 'integer', 'sort_order' => 'integer',
'allocation_value' => 'decimal:2', 'allocation_value' => 'decimal:2',

View file

@ -3,6 +3,7 @@
namespace Database\Factories; namespace Database\Factories;
use App\Enums\BucketAllocationTypeEnum; use App\Enums\BucketAllocationTypeEnum;
use App\Enums\BucketTypeEnum;
use App\Models\Bucket; use App\Models\Bucket;
use App\Models\Scenario; use App\Models\Scenario;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
@ -22,6 +23,11 @@ public function definition(): array
return [ return [
'scenario_id' => Scenario::factory(), 'scenario_id' => Scenario::factory(),
// Overflow excluded — use ->overflow() state modifier
'type' => $this->faker->randomElement([
BucketTypeEnum::NEED,
BucketTypeEnum::WANT,
]),
'name' => $this->faker->randomElement([ 'name' => $this->faker->randomElement([
'Monthly Expenses', 'Monthly Expenses',
'Emergency Fund', 'Emergency Fund',
@ -82,13 +88,46 @@ public function unlimited(): Factory
} }
/** /**
* Create default buckets set (Monthly Expenses, Emergency Fund, Investments). * Create a need bucket.
*/
public function need(): Factory
{
return $this->state([
'type' => BucketTypeEnum::NEED,
]);
}
/**
* Create a want bucket.
*/
public function want(): Factory
{
return $this->state([
'type' => BucketTypeEnum::WANT,
]);
}
/**
* Create an overflow bucket.
*/
public function overflow(): Factory
{
return $this->state([
'type' => BucketTypeEnum::OVERFLOW,
'allocation_type' => BucketAllocationTypeEnum::UNLIMITED,
'allocation_value' => null,
]);
}
/**
* Create default buckets set (Monthly Expenses, Emergency Fund, Overflow).
*/ */
public function defaultSet(): array public function defaultSet(): array
{ {
return [ return [
$this->state([ $this->state([
'name' => 'Monthly Expenses', 'name' => 'Monthly Expenses',
'type' => BucketTypeEnum::NEED,
'priority' => 1, 'priority' => 1,
'sort_order' => 1, 'sort_order' => 1,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
@ -97,6 +136,7 @@ public function defaultSet(): array
]), ]),
$this->state([ $this->state([
'name' => 'Emergency Fund', 'name' => 'Emergency Fund',
'type' => BucketTypeEnum::NEED,
'priority' => 2, 'priority' => 2,
'sort_order' => 2, 'sort_order' => 2,
'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT, 'allocation_type' => BucketAllocationTypeEnum::FIXED_LIMIT,
@ -104,7 +144,8 @@ public function defaultSet(): array
'starting_amount' => 0, 'starting_amount' => 0,
]), ]),
$this->state([ $this->state([
'name' => 'Investments', 'name' => 'Overflow',
'type' => BucketTypeEnum::OVERFLOW,
'priority' => 3, 'priority' => 3,
'sort_order' => 3, 'sort_order' => 3,
'allocation_type' => BucketAllocationTypeEnum::UNLIMITED, 'allocation_type' => BucketAllocationTypeEnum::UNLIMITED,

View file

@ -1,5 +1,6 @@
<?php <?php
use App\Enums\BucketTypeEnum;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@ -12,6 +13,7 @@ public function up(): void
$table->id(); $table->id();
$table->uuid('uuid')->unique(); $table->uuid('uuid')->unique();
$table->foreignId('scenario_id')->constrained()->onDelete('cascade'); $table->foreignId('scenario_id')->constrained()->onDelete('cascade');
$table->enum('type', BucketTypeEnum::values())->default(BucketTypeEnum::NEED->value);
$table->string('name'); $table->string('name');
$table->integer('priority')->comment('Lower number = higher priority, 1 = first'); $table->integer('priority')->comment('Lower number = higher priority, 1 = first');
$table->integer('sort_order')->default(0)->comment('For UI display ordering'); $table->integer('sort_order')->default(0)->comment('For UI display ordering');

View file

@ -0,0 +1,33 @@
<?php
namespace Tests\Unit\Enums;
use App\Enums\BucketTypeEnum;
use PHPUnit\Framework\TestCase;
class BucketTypeEnumTest extends TestCase
{
public function test_has_correct_values(): void
{
$this->assertEquals('need', BucketTypeEnum::NEED->value);
$this->assertEquals('want', BucketTypeEnum::WANT->value);
$this->assertEquals('overflow', BucketTypeEnum::OVERFLOW->value);
}
public function test_has_correct_labels(): void
{
$this->assertEquals('Need', BucketTypeEnum::NEED->getLabel());
$this->assertEquals('Want', BucketTypeEnum::WANT->getLabel());
$this->assertEquals('Overflow', BucketTypeEnum::OVERFLOW->getLabel());
}
public function test_values_returns_all_string_values(): void
{
$values = BucketTypeEnum::values();
$this->assertCount(3, $values);
$this->assertContains('need', $values);
$this->assertContains('want', $values);
$this->assertContains('overflow', $values);
}
}