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

@@ -1,8 +1,8 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateActivityLogTable extends Migration
{

View File

@@ -1,8 +1,8 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddEventColumnToActivityLogTable extends Migration
{

View File

@@ -1,8 +1,8 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddBatchUuidColumnToActivityLogTable extends Migration
{

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
DB::table('media')
->where('model_type', 'App\\Models\\Folder')
->update(['model_type' => 'App\\Models\\Declaration']);
DB::table('activity_log')
->where('subject_type', 'App\\Models\\Folder')
->update(['subject_type' => 'App\\Models\\Declaration']);
}
public function down(): void
{
DB::table('media')
->where('model_type', 'App\\Models\\Declaration')
->update(['model_type' => 'App\\Models\\Folder']);
DB::table('activity_log')
->where('subject_type', 'App\\Models\\Declaration')
->update(['subject_type' => 'App\\Models\\Folder']);
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('workspace_user', function (Blueprint $table) {
$table->json('permissions')->nullable()->default(null)->after('role');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('workspace_user', function (Blueprint $table) {
$table->dropColumn('permissions');
});
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('declarations', function (Blueprint $table) {
$table->timestamp('archived_at')->nullable()->after('deleted_at');
$table->index('archived_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('declarations', function (Blueprint $table) {
$table->dropIndex(['archived_at']);
$table->dropColumn('archived_at');
});
}
};

View File

@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$mapping = [
'draft' => 'created',
'waiting_documents' => 'en_cours',
'documents_received' => 'en_cours',
'processing' => 'en_cours',
'additional_documents_requested' => 'en_attente_client',
'waiting_client_validation' => 'en_attente_client',
'validated' => 'termine',
'closed' => 'ferme',
'cancelled' => 'ferme',
];
foreach ($mapping as $old => $new) {
DB::table('declarations')
->where('status', $old)
->update(['status' => $new]);
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Data migration cannot be reversed — old status distinctions are lost
}
};