diff --git a/app/Enums/DistributionModeEnum.php b/app/Enums/DistributionModeEnum.php new file mode 100644 index 0000000..d74f102 --- /dev/null +++ b/app/Enums/DistributionModeEnum.php @@ -0,0 +1,30 @@ + 'Even Split', + self::PRIORITY => 'Priority Order', + }; + } + + public function getDescription(): string + { + return match ($this) { + self::EVEN => 'Split evenly across buckets in each phase, respecting individual capacity', + self::PRIORITY => 'Fill highest-priority bucket first, then next', + }; + } + + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} diff --git a/app/Http/Resources/ScenarioResource.php b/app/Http/Resources/ScenarioResource.php index 2d4b227..1274cab 100644 --- a/app/Http/Resources/ScenarioResource.php +++ b/app/Http/Resources/ScenarioResource.php @@ -13,6 +13,8 @@ public function toArray(Request $request): array 'id' => $this->uuid, 'name' => $this->name, 'description' => $this->description, + 'distribution_mode' => $this->distribution_mode->value, + 'distribution_mode_label' => $this->distribution_mode->getLabel(), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; diff --git a/app/Models/Scenario.php b/app/Models/Scenario.php index e40ba3f..37aaf72 100644 --- a/app/Models/Scenario.php +++ b/app/Models/Scenario.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\DistributionModeEnum; use App\Models\Traits\HasUuid; use Database\Factories\ScenarioFactory; use Illuminate\Database\Eloquent\Collection; @@ -12,6 +13,7 @@ /** * @property int $id * @property string $uuid + * @property DistributionModeEnum $distribution_mode * @property Collection $buckets * * @method static create(array $data) @@ -24,8 +26,16 @@ class Scenario extends Model protected $fillable = [ 'name', 'description', + 'distribution_mode', ]; + protected function casts(): array + { + return [ + 'distribution_mode' => DistributionModeEnum::class, + ]; + } + public function buckets(): HasMany { return $this->hasMany(Bucket::class); diff --git a/database/factories/ScenarioFactory.php b/database/factories/ScenarioFactory.php index a732f31..7fae415 100644 --- a/database/factories/ScenarioFactory.php +++ b/database/factories/ScenarioFactory.php @@ -2,6 +2,7 @@ namespace Database\Factories; +use App\Enums\DistributionModeEnum; use App\Models\Scenario; use Illuminate\Database\Eloquent\Factories\Factory; @@ -15,6 +16,12 @@ public function definition(): array return [ 'name' => $this->faker->words(2, true).' Budget', 'description' => $this->faker->text, + 'distribution_mode' => DistributionModeEnum::EVEN, ]; } + + public function priority(): static + { + return $this->state(fn () => ['distribution_mode' => DistributionModeEnum::PRIORITY]); + } } diff --git a/database/migrations/2025_12_29_192203_create_scenarios_table.php b/database/migrations/2025_12_29_192203_create_scenarios_table.php index f535fdf..2c4cc4d 100644 --- a/database/migrations/2025_12_29_192203_create_scenarios_table.php +++ b/database/migrations/2025_12_29_192203_create_scenarios_table.php @@ -1,5 +1,6 @@ uuid('uuid')->unique(); $table->string('name'); $table->text('description')->nullable(); + $table->string('distribution_mode')->default(DistributionModeEnum::EVEN->value); $table->timestamps(); }); } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 03a52bc..b2e1d99 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -336,6 +336,12 @@ parameters: count: 1 path: app/Http/Resources/OutflowResource.php + - + message: '#^Access to an undefined property App\\Http\\Resources\\ScenarioResource\:\:\$distribution_mode\.$#' + identifier: property.notFound + count: 2 + path: app/Http/Resources/ScenarioResource.php + - message: '#^Access to an undefined property App\\Http\\Resources\\ScenarioResource\:\:\$created_at\.$#' identifier: property.notFound diff --git a/resources/js/pages/Scenarios/Show.tsx b/resources/js/pages/Scenarios/Show.tsx index c868eec..b65bbcf 100644 --- a/resources/js/pages/Scenarios/Show.tsx +++ b/resources/js/pages/Scenarios/Show.tsx @@ -9,6 +9,8 @@ import IncomeDistributionPreview from '@/components/IncomeDistributionPreview'; interface Scenario { id: string; name: string; + distribution_mode: 'even' | 'priority'; + distribution_mode_label: string; created_at: string; updated_at: string; }