['me:read']], ), new Get( normalizationContext: ['groups' => ['user:list']], ), new GetCollection( normalizationContext: ['groups' => ['user:list']], ), new Post(security: "is_granted('ROLE_ADMIN')", processor: UserPasswordHasherProcessor::class), new Patch(security: "is_granted('ROLE_ADMIN')", processor: UserPasswordHasherProcessor::class), new Delete(security: "is_granted('ROLE_ADMIN')"), ], denormalizationContext: ['groups' => ['user:write']], )] #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: '`user`')] class User implements UserInterface, PasswordAuthenticatedUserInterface { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] #[Groups(['me:read', 'task:read', 'user:list', 'time_entry:read', 'absence_request:read', 'absence_balance:read'])] private ?int $id = null; #[ORM\Column(length: 180, unique: true)] #[Groups(['me:read', 'task:read', 'user:list', 'user:write', 'time_entry:read', 'absence_request:read', 'absence_balance:read'])] private ?string $username = null; /** @var list */ #[ORM\Column] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private array $roles = []; #[ORM\Column] private ?string $password = null; #[Groups(['user:write'])] private ?string $plainPassword = null; #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] private ?DateTimeImmutable $createdAt = null; #[ORM\Column(length: 64, unique: true, nullable: true)] #[Groups(['me:read'])] private ?string $apiToken = null; #[ORM\Column(length: 255, nullable: true)] private ?string $avatarFileName = null; // --- HR / absence management fields (readable only by an admin or the user themselves) --- /** Whether this user is an employee subject to absence management. */ #[ORM\Column] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private bool $isEmployee = false; /** Hiring date — start of paid-leave acquisition. */ #[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private ?DateTimeImmutable $hireDate = null; #[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private ?DateTimeImmutable $endDate = null; #[ORM\Column(type: Types::STRING, length: 16, nullable: true, enumType: ContractType::class)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private ?ContractType $contractType = null; /** Work-time ratio: 1.0 = full time, 0.8 = 4 days out of 5. */ #[ORM\Column(type: Types::FLOAT)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private float $workTimeRatio = 1.0; /** Yearly paid-leave entitlement in worked days (default 25 = jours ouvrés). */ #[ORM\Column(type: Types::FLOAT)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private float $annualLeaveDays = 25.0; /** Reference period start as MM-DD (default 06-01, 1st of June). */ #[ORM\Column(length: 5)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private string $referencePeriodStart = '06-01'; /** Paid-leave already acquired when the module is rolled out. */ #[ORM\Column(type: Types::FLOAT)] #[ApiProperty(security: "is_granted('ROLE_ADMIN') or object == user")] #[Groups(['me:read', 'user:list', 'user:write'])] private float $initialLeaveBalance = 0.0; public function __construct() { $this->createdAt = new DateTimeImmutable(); } public function getId(): ?int { return $this->id; } public function getUsername(): ?string { return $this->username; } public function setUsername(string $username): static { $this->username = $username; return $this; } public function getUserIdentifier(): string { return (string) $this->username; } /** @return list */ public function getRoles(): array { $roles = $this->roles; $roles[] = 'ROLE_USER'; return array_values(array_unique($roles)); } /** @param list $roles */ public function setRoles(array $roles): static { $this->roles = $roles; return $this; } public function getPassword(): ?string { return $this->password; } public function setPassword(string $password): static { $this->password = $password; return $this; } public function getCreatedAt(): ?DateTimeImmutable { return $this->createdAt; } public function setCreatedAt(DateTimeImmutable $createdAt): static { $this->createdAt = $createdAt; return $this; } public function getApiToken(): ?string { return $this->apiToken; } public function setApiToken(?string $apiToken): static { $this->apiToken = $apiToken; return $this; } public function getAvatarFileName(): ?string { return $this->avatarFileName; } public function setAvatarFileName(?string $avatarFileName): static { $this->avatarFileName = $avatarFileName; return $this; } #[Groups(['me:read', 'task:read', 'user:list', 'time_entry:read', 'absence_request:read', 'absence_balance:read'])] public function getAvatarUrl(): ?string { if (null === $this->avatarFileName) { return null; } return '/api/users/'.$this->id.'/avatar'; } public function getPlainPassword(): ?string { return $this->plainPassword; } public function setPlainPassword(?string $plainPassword): static { $this->plainPassword = $plainPassword; return $this; } public function eraseCredentials(): void { $this->plainPassword = null; } public function getIsEmployee(): bool { return $this->isEmployee; } public function setIsEmployee(bool $isEmployee): static { $this->isEmployee = $isEmployee; return $this; } public function getHireDate(): ?DateTimeImmutable { return $this->hireDate; } public function setHireDate(?DateTimeImmutable $hireDate): static { $this->hireDate = $hireDate; return $this; } public function getEndDate(): ?DateTimeImmutable { return $this->endDate; } public function setEndDate(?DateTimeImmutable $endDate): static { $this->endDate = $endDate; return $this; } public function getContractType(): ?ContractType { return $this->contractType; } public function setContractType(?ContractType $contractType): static { $this->contractType = $contractType; return $this; } public function getWorkTimeRatio(): float { return $this->workTimeRatio; } public function setWorkTimeRatio(float $workTimeRatio): static { $this->workTimeRatio = $workTimeRatio; return $this; } public function getAnnualLeaveDays(): float { return $this->annualLeaveDays; } public function setAnnualLeaveDays(float $annualLeaveDays): static { $this->annualLeaveDays = $annualLeaveDays; return $this; } public function getReferencePeriodStart(): string { return $this->referencePeriodStart; } public function setReferencePeriodStart(string $referencePeriodStart): static { $this->referencePeriodStart = $referencePeriodStart; return $this; } public function getInitialLeaveBalance(): float { return $this->initialLeaveBalance; } public function setInitialLeaveBalance(float $initialLeaveBalance): static { $this->initialLeaveBalance = $initialLeaveBalance; return $this; } }