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,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetEvaluationDifficulty;
|
||||
|
||||
final readonly class EvaluationDifficultyDto
|
||||
{
|
||||
public function __construct(
|
||||
public string $evaluationId,
|
||||
public string $title,
|
||||
public string $classId,
|
||||
public string $className,
|
||||
public string $subjectId,
|
||||
public string $subjectName,
|
||||
public string $date,
|
||||
public ?float $average,
|
||||
public int $gradedCount,
|
||||
public ?float $subjectAverage,
|
||||
public ?float $percentile,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetEvaluationDifficulty;
|
||||
|
||||
use App\Scolarite\Application\Port\TeacherStatisticsReader;
|
||||
use App\Scolarite\Domain\Service\TeacherStatisticsCalculator;
|
||||
|
||||
use function array_sum;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
|
||||
#[AsMessageHandler(bus: 'query.bus')]
|
||||
final readonly class GetEvaluationDifficultyHandler
|
||||
{
|
||||
public function __construct(
|
||||
private TeacherStatisticsReader $reader,
|
||||
private TeacherStatisticsCalculator $calculator,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return list<EvaluationDifficultyDto> */
|
||||
public function __invoke(GetEvaluationDifficultyQuery $query): array
|
||||
{
|
||||
$evaluations = $this->reader->teacherEvaluationDifficulties(
|
||||
$query->teacherId,
|
||||
$query->tenantId,
|
||||
);
|
||||
|
||||
/** @var array<string, list<float>> $otherAveragesCache */
|
||||
$otherAveragesCache = [];
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($evaluations as $eval) {
|
||||
/** @var string $subjectId */
|
||||
$subjectId = $eval['subjectId'];
|
||||
|
||||
if (!isset($otherAveragesCache[$subjectId])) {
|
||||
$otherAveragesCache[$subjectId] = $this->reader->subjectAveragesForOtherTeachers(
|
||||
$query->teacherId,
|
||||
$subjectId,
|
||||
$query->tenantId,
|
||||
);
|
||||
}
|
||||
|
||||
$otherAvgs = $otherAveragesCache[$subjectId];
|
||||
$subjectAverage = $otherAvgs !== [] ? round(array_sum($otherAvgs) / count($otherAvgs), 2) : null;
|
||||
$percentile = $eval['average'] !== null && $otherAvgs !== []
|
||||
? $this->calculator->calculatePercentile($eval['average'], $otherAvgs)
|
||||
: null;
|
||||
|
||||
$results[] = new EvaluationDifficultyDto(
|
||||
evaluationId: $eval['evaluationId'],
|
||||
title: $eval['title'],
|
||||
classId: $eval['classId'],
|
||||
className: $eval['className'],
|
||||
subjectId: $subjectId,
|
||||
subjectName: $eval['subjectName'],
|
||||
date: $eval['date'],
|
||||
average: $eval['average'],
|
||||
gradedCount: $eval['gradedCount'],
|
||||
subjectAverage: $subjectAverage,
|
||||
percentile: $percentile,
|
||||
);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetEvaluationDifficulty;
|
||||
|
||||
final readonly class GetEvaluationDifficultyQuery
|
||||
{
|
||||
public function __construct(
|
||||
public string $teacherId,
|
||||
public string $tenantId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user