feat: Provisionner automatiquement un nouvel établissement
Lorsqu'un super-admin crée un établissement via l'interface, le système doit automatiquement créer la base tenant, exécuter les migrations, créer le premier utilisateur admin et envoyer l'invitation — le tout de manière asynchrone pour ne pas bloquer la réponse HTTP. Ce mécanisme rend chaque établissement opérationnel dès sa création sans intervention manuelle sur l'infrastructure.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Scolarite\Application\Query\GetEvaluationDifficulty;
|
||||
|
||||
use App\Scolarite\Application\Query\GetEvaluationDifficulty\GetEvaluationDifficultyHandler;
|
||||
use App\Scolarite\Application\Query\GetEvaluationDifficulty\GetEvaluationDifficultyQuery;
|
||||
use App\Scolarite\Domain\Service\TeacherStatisticsCalculator;
|
||||
use App\Scolarite\Infrastructure\ReadModel\InMemoryTeacherStatisticsReader;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class GetEvaluationDifficultyHandlerTest extends TestCase
|
||||
{
|
||||
private const string TEACHER_ID = '550e8400-e29b-41d4-a716-446655440010';
|
||||
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
||||
|
||||
private InMemoryTeacherStatisticsReader $reader;
|
||||
private GetEvaluationDifficultyHandler $handler;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->reader = new InMemoryTeacherStatisticsReader();
|
||||
$this->handler = new GetEvaluationDifficultyHandler(
|
||||
$this->reader,
|
||||
new TeacherStatisticsCalculator(),
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itReturnsEmptyWhenNoEvaluations(): void
|
||||
{
|
||||
$result = ($this->handler)($this->query());
|
||||
|
||||
self::assertSame([], $result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itReturnsEvaluationDifficultyWithComparison(): void
|
||||
{
|
||||
$this->reader->feedEvaluationDifficulties([
|
||||
[
|
||||
'evaluationId' => 'eval-1',
|
||||
'title' => 'Contrôle chapitre 5',
|
||||
'classId' => 'class-1',
|
||||
'className' => '6ème A',
|
||||
'subjectId' => 'subject-1',
|
||||
'subjectName' => 'Mathématiques',
|
||||
'date' => '2026-03-15',
|
||||
'average' => 12.0,
|
||||
'gradedCount' => 25,
|
||||
],
|
||||
]);
|
||||
|
||||
// Other teachers' averages for same subject
|
||||
$this->reader->feedOtherTeachersAverages([10.0, 11.0, 13.0]);
|
||||
|
||||
$result = ($this->handler)($this->query());
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertSame('Contrôle chapitre 5', $result[0]->title);
|
||||
self::assertSame(12.0, $result[0]->average);
|
||||
self::assertEqualsWithDelta(11.33, $result[0]->subjectAverage, 0.01);
|
||||
self::assertNotNull($result[0]->percentile);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itHandlesNoOtherTeachersForComparison(): void
|
||||
{
|
||||
$this->reader->feedEvaluationDifficulties([
|
||||
[
|
||||
'evaluationId' => 'eval-1',
|
||||
'title' => 'Test unique',
|
||||
'classId' => 'class-1',
|
||||
'className' => '6ème A',
|
||||
'subjectId' => 'subject-1',
|
||||
'subjectName' => 'Musique',
|
||||
'date' => '2026-03-15',
|
||||
'average' => 14.0,
|
||||
'gradedCount' => 20,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->reader->feedOtherTeachersAverages([]);
|
||||
|
||||
$result = ($this->handler)($this->query());
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertNull($result[0]->subjectAverage);
|
||||
self::assertNull($result[0]->percentile);
|
||||
}
|
||||
|
||||
private function query(): GetEvaluationDifficultyQuery
|
||||
{
|
||||
return new GetEvaluationDifficultyQuery(
|
||||
teacherId: self::TEACHER_ID,
|
||||
tenantId: self::TENANT_ID,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user