feat: Permettre au parent de consulter les devoirs de ses enfants
Les parents avaient accès à l'emploi du temps de leurs enfants mais pas à leurs devoirs. Sans cette visibilité, ils ne pouvaient pas accompagner efficacement le travail scolaire à la maison, notamment identifier les devoirs urgents ou contacter l'enseignant en cas de besoin. Le parent dispose désormais d'une vue consolidée multi-enfants avec filtrage par enfant et par matière, badges d'urgence différenciés (en retard / aujourd'hui / pour demain), lien de contact enseignant pré-rempli, et cache offline scopé par utilisateur.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetChildrenHomework;
|
||||
|
||||
use App\Scolarite\Application\Query\GetStudentHomework\StudentHomeworkDto;
|
||||
|
||||
final readonly class ChildHomeworkDto
|
||||
{
|
||||
/**
|
||||
* @param array<StudentHomeworkDto> $homework
|
||||
*/
|
||||
public function __construct(
|
||||
public string $childId,
|
||||
public string $firstName,
|
||||
public string $lastName,
|
||||
public array $homework,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetChildrenHomework;
|
||||
|
||||
use App\Scolarite\Application\Port\ParentChildrenReader;
|
||||
use App\Scolarite\Application\Port\ScheduleDisplayReader;
|
||||
use App\Scolarite\Application\Port\StudentClassReader;
|
||||
use App\Scolarite\Application\Query\GetStudentHomework\StudentHomeworkDetailDto;
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkId;
|
||||
use App\Scolarite\Domain\Repository\HomeworkAttachmentRepository;
|
||||
use App\Scolarite\Domain\Repository\HomeworkRepository;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
|
||||
final readonly class GetChildrenHomeworkDetailHandler
|
||||
{
|
||||
public function __construct(
|
||||
private ParentChildrenReader $parentChildrenReader,
|
||||
private StudentClassReader $studentClassReader,
|
||||
private HomeworkRepository $homeworkRepository,
|
||||
private HomeworkAttachmentRepository $attachmentRepository,
|
||||
private ScheduleDisplayReader $displayReader,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(string $parentId, string $tenantId, string $homeworkId): ?StudentHomeworkDetailDto
|
||||
{
|
||||
$tid = TenantId::fromString($tenantId);
|
||||
|
||||
$homework = $this->homeworkRepository->findById(HomeworkId::fromString($homeworkId), $tid);
|
||||
|
||||
if ($homework === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$this->parentHasChildInClass($parentId, $tid, (string) $homework->classId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$attachments = $this->attachmentRepository->findByHomeworkId($homework->id);
|
||||
|
||||
$subjects = $this->displayReader->subjectDisplay($tenantId, (string) $homework->subjectId);
|
||||
$teacherNames = $this->displayReader->teacherNames($tenantId, (string) $homework->teacherId);
|
||||
|
||||
return StudentHomeworkDetailDto::fromDomain(
|
||||
$homework,
|
||||
$subjects[(string) $homework->subjectId]['name'] ?? '',
|
||||
$subjects[(string) $homework->subjectId]['color'] ?? null,
|
||||
$teacherNames[(string) $homework->teacherId] ?? '',
|
||||
$attachments,
|
||||
);
|
||||
}
|
||||
|
||||
private function parentHasChildInClass(string $parentId, TenantId $tenantId, string $homeworkClassId): bool
|
||||
{
|
||||
$children = $this->parentChildrenReader->childrenOf($parentId, $tenantId);
|
||||
|
||||
foreach ($children as $child) {
|
||||
$classId = $this->studentClassReader->currentClassId($child['studentId'], $tenantId);
|
||||
|
||||
if ($classId === $homeworkClassId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetChildrenHomework;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
||||
use App\Scolarite\Application\Port\ParentChildrenReader;
|
||||
use App\Scolarite\Application\Port\ScheduleDisplayReader;
|
||||
use App\Scolarite\Application\Port\StudentClassReader;
|
||||
use App\Scolarite\Application\Query\GetStudentHomework\StudentHomeworkDto;
|
||||
use App\Scolarite\Domain\Model\Homework\Homework;
|
||||
use App\Scolarite\Domain\Model\Homework\HomeworkId;
|
||||
use App\Scolarite\Domain\Repository\HomeworkAttachmentRepository;
|
||||
use App\Scolarite\Domain\Repository\HomeworkRepository;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function array_unique;
|
||||
use function array_values;
|
||||
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
|
||||
use function usort;
|
||||
|
||||
#[AsMessageHandler(bus: 'query.bus')]
|
||||
final readonly class GetChildrenHomeworkHandler
|
||||
{
|
||||
public function __construct(
|
||||
private ParentChildrenReader $parentChildrenReader,
|
||||
private StudentClassReader $studentClassReader,
|
||||
private HomeworkRepository $homeworkRepository,
|
||||
private HomeworkAttachmentRepository $attachmentRepository,
|
||||
private ScheduleDisplayReader $displayReader,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return array<ChildHomeworkDto> */
|
||||
public function __invoke(GetChildrenHomeworkQuery $query): array
|
||||
{
|
||||
$tenantId = TenantId::fromString($query->tenantId);
|
||||
$allChildren = $this->parentChildrenReader->childrenOf($query->parentId, $tenantId);
|
||||
|
||||
if ($allChildren === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$children = $query->childId !== null
|
||||
? array_values(array_filter($allChildren, static fn (array $c): bool => $c['studentId'] === $query->childId))
|
||||
: $allChildren;
|
||||
|
||||
if ($children === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($children as $child) {
|
||||
$classId = $this->studentClassReader->currentClassId($child['studentId'], $tenantId);
|
||||
|
||||
if ($classId === null) {
|
||||
$result[] = new ChildHomeworkDto(
|
||||
childId: $child['studentId'],
|
||||
firstName: $child['firstName'],
|
||||
lastName: $child['lastName'],
|
||||
homework: [],
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$homeworks = $this->homeworkRepository->findByClass(ClassId::fromString($classId), $tenantId);
|
||||
|
||||
if ($query->subjectId !== null) {
|
||||
$filterSubjectId = $query->subjectId;
|
||||
$homeworks = array_values(array_filter(
|
||||
$homeworks,
|
||||
static fn (Homework $h): bool => (string) $h->subjectId === $filterSubjectId,
|
||||
));
|
||||
}
|
||||
|
||||
usort($homeworks, static fn (Homework $a, Homework $b): int => $a->dueDate <=> $b->dueDate);
|
||||
|
||||
$enriched = $this->enrichHomeworks($homeworks, $query->tenantId);
|
||||
|
||||
$result[] = new ChildHomeworkDto(
|
||||
childId: $child['studentId'],
|
||||
firstName: $child['firstName'],
|
||||
lastName: $child['lastName'],
|
||||
homework: $enriched,
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<Homework> $homeworks
|
||||
*
|
||||
* @return array<StudentHomeworkDto>
|
||||
*/
|
||||
private function enrichHomeworks(array $homeworks, string $tenantId): array
|
||||
{
|
||||
if ($homeworks === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$subjectIds = array_values(array_unique(
|
||||
array_map(static fn (Homework $h): string => (string) $h->subjectId, $homeworks),
|
||||
));
|
||||
$teacherIds = array_values(array_unique(
|
||||
array_map(static fn (Homework $h): string => (string) $h->teacherId, $homeworks),
|
||||
));
|
||||
|
||||
$subjects = $this->displayReader->subjectDisplay($tenantId, ...$subjectIds);
|
||||
$teacherNames = $this->displayReader->teacherNames($tenantId, ...$teacherIds);
|
||||
|
||||
$homeworkIds = array_map(static fn (Homework $h): HomeworkId => $h->id, $homeworks);
|
||||
$attachmentMap = $this->attachmentRepository->hasAttachments(...$homeworkIds);
|
||||
|
||||
return array_map(
|
||||
static fn (Homework $h): StudentHomeworkDto => StudentHomeworkDto::fromDomain(
|
||||
$h,
|
||||
$subjects[(string) $h->subjectId]['name'] ?? '',
|
||||
$subjects[(string) $h->subjectId]['color'] ?? null,
|
||||
$teacherNames[(string) $h->teacherId] ?? '',
|
||||
$attachmentMap[(string) $h->id] ?? false,
|
||||
),
|
||||
$homeworks,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Scolarite\Application\Query\GetChildrenHomework;
|
||||
|
||||
final readonly class GetChildrenHomeworkQuery
|
||||
{
|
||||
public function __construct(
|
||||
public string $parentId,
|
||||
public string $tenantId,
|
||||
public ?string $childId = null,
|
||||
public ?string $subjectId = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user