feat(mail) : MailCreateTaskController - POST /api/mail/messages/{id}/create-task
- cree une Task avec titre = subject du mail (max 255 chars) - utilise findMaxNumberByProjectForUpdate pour numero (advisory lock PG) - transaction wrapInTransaction pour eviter race conditions - taskGroupId et priorityId optionnels via body JSON - cree automatiquement le TaskMailLink (mail <-> tache) - retourne 201 + taskId/taskNumber/taskTitle/messageId Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
105
src/Controller/Mail/MailCreateTaskController.php
Normal file
105
src/Controller/Mail/MailCreateTaskController.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Task;
|
||||
use App\Entity\TaskGroup;
|
||||
use App\Entity\TaskMailLink;
|
||||
use App\Entity\TaskPriority;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Repository\TaskRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route('/api/mail/messages/{id}/create-task', name: 'mail_create_task', methods: ['POST'], priority: 1, requirements: ['id' => '\d+'])]
|
||||
#[IsGranted('IS_AUTHENTICATED_FULLY')]
|
||||
class MailCreateTaskController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
private readonly TaskRepository $taskRepository,
|
||||
) {}
|
||||
|
||||
public function __invoke(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
|
||||
$body = json_decode($request->getContent(), true);
|
||||
$projectId = $body['projectId'] ?? null;
|
||||
|
||||
if (null === $projectId) {
|
||||
throw new UnprocessableEntityHttpException('projectId is required');
|
||||
}
|
||||
|
||||
$project = $this->em->getRepository(Project::class)->find($projectId);
|
||||
if (null === $project) {
|
||||
throw new NotFoundHttpException('Project not found');
|
||||
}
|
||||
|
||||
$title = $message->getSubject() ?? 'Mail sans sujet';
|
||||
if (mb_strlen($title) > 255) {
|
||||
$title = mb_substr($title, 0, 252).'...';
|
||||
}
|
||||
|
||||
$result = $this->em->wrapInTransaction(function () use ($project, $title, $body, $message) {
|
||||
$maxNumber = $this->taskRepository->findMaxNumberByProjectForUpdate($project);
|
||||
|
||||
$task = new Task();
|
||||
$task->setProject($project);
|
||||
$task->setTitle($title);
|
||||
$task->setNumber($maxNumber + 1);
|
||||
|
||||
if (isset($body['taskGroupId']) && null !== $body['taskGroupId']) {
|
||||
$taskGroup = $this->em->getRepository(TaskGroup::class)->find($body['taskGroupId']);
|
||||
if (null !== $taskGroup) {
|
||||
$task->setGroup($taskGroup);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($body['priorityId']) && null !== $body['priorityId']) {
|
||||
$priority = $this->em->getRepository(TaskPriority::class)->find($body['priorityId']);
|
||||
if (null !== $priority) {
|
||||
$task->setPriority($priority);
|
||||
}
|
||||
}
|
||||
|
||||
$this->em->persist($task);
|
||||
|
||||
$link = new TaskMailLink();
|
||||
$link->setTask($task);
|
||||
$link->setMailMessage($message);
|
||||
$link->setLinkedAt(new DateTimeImmutable());
|
||||
$link->setLinkedBy($this->getUser());
|
||||
$this->em->persist($link);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
return $task;
|
||||
});
|
||||
|
||||
return $this->json([
|
||||
'taskId' => $result->getId(),
|
||||
'taskNumber' => $result->getNumber(),
|
||||
'taskTitle' => $result->getTitle(),
|
||||
'messageId' => $message->getId(),
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user