['task:read']], denormalizationContext: ['groups' => ['task:write']], order: ['id' => 'DESC'], )] #[ApiFilter(SearchFilter::class, properties: ['project' => 'exact', 'group' => 'exact', 'assignee' => 'exact', 'priority' => 'exact', 'effort' => 'exact', 'tags' => 'exact', 'status' => 'exact'])] #[ApiFilter(DateFilter::class, properties: ['scheduledStart', 'scheduledEnd', 'deadline'])] #[ApiFilter(BooleanFilter::class, properties: ['archived', 'syncToCalendar'])] #[ApiFilter(OrderFilter::class, properties: ['scheduledStart', 'deadline'])] #[ORM\Entity(repositoryClass: TaskRepository::class)] #[ORM\Table(name: 'task')] #[ORM\UniqueConstraint(name: 'uniq_task_project_number', columns: ['project_id', 'number'])] class Task { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] #[Groups(['task:read'])] private ?int $id = null; #[ORM\Column(type: 'integer')] #[Groups(['task:read'])] private ?int $number = null; #[ORM\Column(length: 255)] #[Groups(['task:read', 'task:write'])] private ?string $title = null; #[ORM\Column(type: 'text', nullable: true)] #[Groups(['task:read', 'task:write'])] private ?string $description = null; #[ORM\ManyToOne(targetEntity: TaskStatus::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?TaskStatus $status = null; #[ORM\ManyToOne(targetEntity: TaskEffort::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?TaskEffort $effort = null; #[ORM\ManyToOne(targetEntity: TaskPriority::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?TaskPriority $priority = null; #[ORM\ManyToOne(targetEntity: User::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?User $assignee = null; #[ORM\ManyToOne(targetEntity: TaskGroup::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?TaskGroup $group = null; #[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'tasks')] #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] #[Groups(['task:read', 'task:write'])] private ?Project $project = null; /** @var Collection */ #[ORM\ManyToMany(targetEntity: TaskTag::class)] #[ORM\JoinTable( name: 'task_task_type', joinColumns: [new ORM\JoinColumn(name: 'task_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'task_type_id', referencedColumnName: 'id')], )] #[Groups(['task:read', 'task:write'])] private Collection $tags; #[ORM\Column(type: 'boolean')] #[Groups(['task:read', 'task:write'])] private bool $archived = false; /** @var Collection */ #[ORM\OneToMany(targetEntity: TaskDocument::class, mappedBy: 'task', cascade: ['remove'])] #[Groups(['task:read'])] private Collection $documents; #[ORM\ManyToOne(targetEntity: ClientTicket::class)] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?ClientTicket $clientTicket = null; #[ORM\Column(type: 'datetime_immutable', nullable: true)] #[Groups(['task:read', 'task:write'])] private ?DateTimeImmutable $scheduledStart = null; #[ORM\Column(type: 'datetime_immutable', nullable: true)] #[Groups(['task:read', 'task:write'])] private ?DateTimeImmutable $scheduledEnd = null; #[ORM\Column(type: 'datetime_immutable', nullable: true)] #[Groups(['task:read', 'task:write'])] private ?DateTimeImmutable $deadline = null; #[ORM\Column(type: 'boolean', options: ['default' => false])] #[Groups(['task:read', 'task:write'])] private bool $syncToCalendar = false; #[ORM\Column(length: 255, nullable: true)] private ?string $calendarEventUid = null; #[ORM\Column(length: 255, nullable: true)] private ?string $calendarTodoUid = null; #[ORM\Column(type: 'text', nullable: true)] #[Groups(['task:read'])] private ?string $calendarSyncError = null; #[ORM\ManyToOne(targetEntity: TaskRecurrence::class, inversedBy: 'tasks')] #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] #[Groups(['task:read', 'task:write'])] private ?TaskRecurrence $recurrence = null; public function __construct() { $this->tags = new ArrayCollection(); $this->documents = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getNumber(): ?int { return $this->number; } public function setNumber(int $number): static { $this->number = $number; return $this; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): static { $this->title = $title; return $this; } public function getDescription(): ?string { return $this->description; } public function setDescription(?string $description): static { $this->description = $description; return $this; } public function getStatus(): ?TaskStatus { return $this->status; } public function setStatus(?TaskStatus $status): static { $this->status = $status; return $this; } public function getEffort(): ?TaskEffort { return $this->effort; } public function setEffort(?TaskEffort $effort): static { $this->effort = $effort; return $this; } public function getPriority(): ?TaskPriority { return $this->priority; } public function setPriority(?TaskPriority $priority): static { $this->priority = $priority; return $this; } public function getAssignee(): ?User { return $this->assignee; } public function setAssignee(?User $assignee): static { $this->assignee = $assignee; return $this; } public function getGroup(): ?TaskGroup { return $this->group; } public function setGroup(?TaskGroup $group): static { $this->group = $group; return $this; } public function getProject(): ?Project { return $this->project; } public function setProject(?Project $project): static { $this->project = $project; return $this; } /** @return Collection */ public function getTags(): Collection { return $this->tags; } public function addTag(TaskTag $tag): static { if (!$this->tags->contains($tag)) { $this->tags->add($tag); } return $this; } public function removeTag(TaskTag $tag): static { $this->tags->removeElement($tag); return $this; } public function isArchived(): bool { return $this->archived; } public function setArchived(bool $archived): static { $this->archived = $archived; return $this; } /** @return Collection */ public function getDocuments(): Collection { return $this->documents; } public function getClientTicket(): ?ClientTicket { return $this->clientTicket; } public function setClientTicket(?ClientTicket $clientTicket): static { $this->clientTicket = $clientTicket; return $this; } public function getScheduledStart(): ?DateTimeImmutable { return $this->scheduledStart; } public function setScheduledStart(?DateTimeImmutable $scheduledStart): static { $this->scheduledStart = $scheduledStart; return $this; } public function getScheduledEnd(): ?DateTimeImmutable { return $this->scheduledEnd; } public function setScheduledEnd(?DateTimeImmutable $scheduledEnd): static { $this->scheduledEnd = $scheduledEnd; return $this; } public function getDeadline(): ?DateTimeImmutable { return $this->deadline; } public function setDeadline(?DateTimeImmutable $deadline): static { $this->deadline = $deadline; return $this; } public function isSyncToCalendar(): bool { return $this->syncToCalendar; } public function setSyncToCalendar(bool $syncToCalendar): static { $this->syncToCalendar = $syncToCalendar; return $this; } public function getCalendarEventUid(): ?string { return $this->calendarEventUid; } public function setCalendarEventUid(?string $calendarEventUid): static { $this->calendarEventUid = $calendarEventUid; return $this; } public function getCalendarTodoUid(): ?string { return $this->calendarTodoUid; } public function setCalendarTodoUid(?string $calendarTodoUid): static { $this->calendarTodoUid = $calendarTodoUid; return $this; } public function getCalendarSyncError(): ?string { return $this->calendarSyncError; } public function setCalendarSyncError(?string $calendarSyncError): static { $this->calendarSyncError = $calendarSyncError; return $this; } public function getRecurrence(): ?TaskRecurrence { return $this->recurrence; } public function setRecurrence(?TaskRecurrence $recurrence): static { $this->recurrence = $recurrence; return $this; } #[Assert\Callback] public function validateScheduledDates(ExecutionContextInterface $context): void { if ((null === $this->scheduledStart) !== (null === $this->scheduledEnd)) { $context->buildViolation('scheduledStart and scheduledEnd must both be set or both be null.') ->atPath('scheduledEnd') ->addViolation() ; } if (null !== $this->scheduledStart && null !== $this->scheduledEnd && $this->scheduledEnd <= $this->scheduledStart) { $context->buildViolation('scheduledEnd must be after scheduledStart.') ->atPath('scheduledEnd') ->addViolation() ; } } }