feat: complete Epic 0 — foundation migration & infrastructure setup

Stories 0.2-0.5: rename folders→declarations (backend+frontend), configure
Redis for cache/queue/sessions, add foundation database migrations
(permissions, archived_at), replace DeclarationStatus enum with architecture
lifecycle values, create DeclarationObserver for status transition validation
and auto-archive, fix controller status transitions to respect observer rules.

93 tests pass (240 assertions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 18:25:32 +00:00
parent d380df4074
commit fd43a6f429
105 changed files with 3899 additions and 1558 deletions

View File

@@ -2,17 +2,17 @@
namespace Database\Factories;
use App\Enums\FolderPriority;
use App\Enums\FolderStatus;
use App\Enums\FolderType;
use App\Enums\DeclarationPriority;
use App\Enums\DeclarationStatus;
use App\Enums\DeclarationType;
use App\Models\Client;
use App\Models\Workspace;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Folder>
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Declaration>
*/
class FolderFactory extends Factory
class DeclarationFactory extends Factory
{
/**
* Define the model's default state.
@@ -25,7 +25,7 @@ class FolderFactory extends Factory
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
$year = fake()->numberBetween(2024, 2026);
$excludeOldVat = array_filter(FolderType::getValues(), fn ($v) => $v !== 'vat');
$excludeOldVat = array_filter(DeclarationType::getValues(), fn ($v) => $v !== 'vat');
$type = fake()->randomElement(array_values($excludeOldVat));
$isVatMonthly = $type === 'vat_monthly';
@@ -41,8 +41,8 @@ class FolderFactory extends Factory
'period_month' => $isVatMonthly ? fake()->numberBetween(1, 12) : null,
'period_quarter' => $isVatQuarterly ? fake()->numberBetween(1, 4) : null,
'due_date' => fake()->dateTimeBetween('now', '+3 months'),
'status' => fake()->randomElement(FolderStatus::getValues()),
'priority' => fake()->randomElement(FolderPriority::getValues()),
'status' => DeclarationStatus::Created,
'priority' => fake()->randomElement(DeclarationPriority::getValues()),
'assigned_to' => null,
'validated_at' => null,
'closed_at' => null,