<?php
namespace App\Entity;
use App\Entity\Reference\PersonTypeReference;
use App\Traits\TimeStampTrait;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\Constraints as Assert;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use App\ApiPlatform\Filter\RoleSearchFilter;
use App\Entity\Reference\ReferenceCollaboratorStatus;
use App\Entity\Reference\ReferencePersonMaritalStatus;
use App\Repository\AbstractCollaboratorRepository;
use App\Filter\FullNameSearchFilter;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use App\ApiPlatform\Filter\CurrentUserFilter;
use App\Filter\DirectoryListFilter;
use App\Controller\Admin\UpdatePasswordController;
use App\Filter\CustomMainPhoneFilter;
use App\Filter\ReferenceStateFilter;
/**
* @ApiResource(
* security= "is_granted('ROLE_AGENT') or is_granted('ROLE_MANAGER')",
* normalizationContext={"groups"={"abstract-collaborator:read","directory:collaborator:search"},
* "swagger_definition_name"="Read"},
* denormalizationContext={"groups"={"abstract-collaborator:write"}, "swagger_definition_name"="Write",
* "skip_null_values" = true},
* itemOperations={
* "get" = {
* "path"="/collaborators/{id}"
* },
* "put" = {
* "denormalization_context"={"groups"={"abstract-collaborator:put"},"skip_null_values" = true},
* "security" = "is_granted('PROFILE_UPDATE', object)" ,
* },
* "update_password" = {
* "method"="PATCH",
* "access_control"="is_granted('ROLE_ADMIN')",
* "path"="/collaborators/{id}/update_password",
* "controller"=UpdatePasswordController::class,
* "openapi_context"={
* "summary"="Update password",
* "description"="Update password of users by Admin"
* }
* }
* },
* collectionOperations={
* "get" = {
* "path"="/collaborators"
* },
* },
* attributes={
* "pagination_items_per_page"=10,
* "formats"={"jsonld", "json", "html", "jsonhal", "csv"={"text/csv"} }
* }
* )
*
* @ApiFilter(CurrentUserFilter::class)
* @ApiFilter(SearchFilter::class, properties={
* "id": "exact",
* "firstName": "ipartial",
* "lastName": "ipartial",
* "email": "partial",
* "professionalEmail": "partial",
* "address.city.name":"ipartial",
* "referenceStatus": "exact"
* })
*
* @ApiFilter(CustomMainPhoneFilter::class, properties={"mainPhone"})
* @ApiFilter(FullNameSearchFilter::class)
* @ApiFilter(DirectoryListFilter::class, properties={"isDirectory"})
* @ApiFilter(ReferenceStateFilter::class, properties={"referenceState"})
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="type", type="string", length=12)
* @ORM\DiscriminatorMap({
* "agent"="Agent",
* "manager" = "Manager",
* "managerBack" = "ManagerBackOffice",
* "managerIt" = "ManagerIt"
* })
*
* @ORM\Entity(repositoryClass=AbstractCollaboratorRepository::class)
* @ORM\Table(indexes={@ORM\Index(name="abstract_collaborator_search_idx", columns={"first_name","last_name",
* "email","main_phone"})})
* @ORM\HasLifecycleCallbacks()
*
*/
abstract class AbstractCollaborator implements UserInterface, PasswordAuthenticatedUserInterface
{
use TimeStampTrait;
public const ROLE_AGENT = 'ROLE_AGENT';
public const ROLE_MANAGER = 'ROLE_MANAGER';
public const ROLE_ADMIN = 'ROLE_ADMIN';
public const ROLE_MANAGER_IT = 'ROLE_IT';
public const ROLE_MANAGER_BACK_OFFICE = 'ROLE_BACK';
public const ROLE_CONSTELLATION_HEAD = 'ROLE_CONSTELLATION_HEAD';
public const ROLE_BUSINESS_INDICATION = 'ROLE_BUSINESS_INDICATION';
public const ROLE_PUBLIC_ACCESS = 'ROLE_PUBLIC_ACCESS';
public const ALL_ROLES = [
self::ROLE_AGENT,
self::ROLE_MANAGER,
self::ROLE_ADMIN,
self::ROLE_MANAGER_IT,
self::ROLE_MANAGER_BACK_OFFICE,
self::ROLE_CONSTELLATION_HEAD,
self::ROLE_BUSINESS_INDICATION,
];
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "prescriber:read",
* "contact:read",
* "genealogy:read",
* "mandate:read",
* "property:read",
* "agent:read",
* "transaction-item:read",
* "milkiya:read",
* "business-indication:item:read",
* "business-indication:collection:read",
* "manager:read",
* "agent:light"
* })
*/
protected ?int $id;
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\Sequentially({
* @Assert\NotBlank(),
* @Assert\Type("string"),
* @Assert\Length(
* min = 2,
* max = 253,
* minMessage = "First Name must be at least {{ limit }} characters long",
* maxMessage = "First Name cannot be longer than {{ limit }} characters"
* ),
* })
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "prescriber:read",
* "genealogy:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "transaction-item:read",
* "transaction:collection:read",
* "business-indication:item:read",
* "business-indication:collection:read",
* "manager:read",
* "milkiya:read",
* "agent:light"
* })
*
*/
protected ?string $firstName;
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\Sequentially({
* @Assert\NotBlank(),
* @Assert\Type("string"),
* @Assert\Length(
* min = 2,
* max = 253,
* minMessage = "Last Name must be at least {{ limit }} characters long",
* maxMessage = "Last Name cannot be longer than {{ limit }} characters"
* ),
* })
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "prescriber:read",
* "genealogy:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "transaction-item:read",
* "transaction:collection:read",
* "business-indication:item:read",
* "business-indication:collection:read",
* "manager:read",
* "milkiya:read",
* "agent:light"
* })
*/
protected ?string $lastName;
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\Sequentially({
* @Assert\NotBlank(),
* @Assert\Email(),
* @Assert\Length(
* min = 2,
* max = 253,
* minMessage = "Email must be at least {{ limit }} characters long",
* maxMessage = "Email cannot be longer than {{ limit }} characters"
* ),
* })
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "transaction-item:read",
* "business-indication:item:read",
* })
*/
protected ?string $email;
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\Sequentially({
* @Assert\NotBlank(),
* @Assert\Email(),
* @Assert\Length(
* min = 2,
* max = 253,
* minMessage = "Professional Email must be at least {{ limit }} characters long",
* maxMessage = "Professional Email cannot be longer than {{ limit }} characters"
* ),
* })
*
* @Groups({
* "directory:collaborator:search",
* "abstract-collaborator:read",
* "candidate:read",
* "contact:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "transaction-item:read",
* "milkiya:read",
* "agent:light"
* })
*/
protected ?string $professionalEmail;
/**
* @ORM\Column(type="date", nullable=true)
* @Assert\LessThan("-18 years")
* @Groups({
* "directory:collaborator:search",
* "abstract-collaborator:read",
* "candidate:read",
* "contact:read",
* "mandate:read:private",
* "property:read",
* "agent:read","siege:put","siege:write",
* "business-indication:item:read",
* })
*
*/
protected $birthDay;
/**
* @ORM\Column(type="string", length=255,nullable=true)
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","abstract-collaborator:put","siege:write",
* })
*/
protected ?string $phone;
/**
* @ORM\Column(type="string", length=255)
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","abstract-collaborator:put","siege:write",
* "recommandation:read",
* "milkiya:read"
* })
*/
protected ?string $mainPhone;
/**
* @ORM\OneToOne(targetEntity=Address::class, cascade={"persist", "remove"})
* @ORM\JoinColumn(nullable=false)
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "mandate:read:private",
* "property:read",
* "agent:read","siege:put","abstract-collaborator:put","siege:write"
* })
*/
protected ?Address $address;
/**
* @ORM\ManyToOne(targetEntity=Gender::class, inversedBy="abstractPeople")
* @ORM\JoinColumn(nullable=false)
*
* @Groups({
* "directory:collaborator:search",
* "abstract-collaborator:read",
* "candidate:read",
* "contact:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "milkiya:read"
* })
*/
protected ?Gender $gender;
/**
* @ORM\Column(type="json")
* @ApiFilter(RoleSearchFilter::class)
* @Groups({
* "directory:collaborator:search",
* "abstract-collaborator:read",
* "agent:read",
* "siege:write",
* })
*/
protected array $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
* @Groups({
* "siege:write",
* })
*
*/
protected string $password;
/**
*
*/
protected ?string $plainPassword;
/**
* @ORM\ManyToOne(targetEntity=ReferenceCollaboratorStatus::class, inversedBy="collaborators")
* @ORM\JoinColumn(nullable=true)
*
* @Groups({
* "directory:collaborator:search",
* "abstract-colloborator:read",
* "agent:read","siege:put",
* })
*/
private ?ReferenceCollaboratorStatus $referenceStatus;
/**
* @ORM\ManyToOne(targetEntity=ReferencePersonMaritalStatus::class)
* @ORM\JoinColumn(nullable=true)
*
* @Groups({
* "agent:read","agent:put","siege:put",
* "directory:collaborator:search",
* "abstract-colloborator:read"
* })
*
*/
private ?ReferencePersonMaritalStatus $referenceMaritalStatus;
/**
* @ORM\OneToOne(targetEntity=Avatar::class, mappedBy="collaborator", cascade={"persist", "remove"})
*
* @Groups({
* "directory:collaborator:search",
* "abstract-colloborator:read",
* "agent:read","siege:put",
* "milkiya:read"
* })
*/
private ?Avatar $avatar;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $lastConnection;
/**
* @ORM\OneToOne(targetEntity=Cgu::class, mappedBy="collaborator", cascade={"persist", "remove"})
* @Groups({
* "directory:collaborator:search",
* "abstract-collaborator:read",
* "agent:read",
* })
*/
private $cgu;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*
* @Groups({
* "directory:collaborator:search",
* "siege:put","siege:write",
* "agent:read",
* "siege:write"
* })
*/
private ?string $personType = null;
public function __construct()
{
}
public function getId(): ?int
{
return $this->id;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getBirthDay(): ?DateTimeInterface
{
return $this->birthDay;
}
public function setBirthDay(?DateTimeInterface $birthDay): self
{
$this->birthDay = $birthDay;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getMainPhone(): ?string
{
return $this->mainPhone;
}
public function setMainPhone(string $mainPhone): self
{
$this->mainPhone = $mainPhone;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
/**
* @param string $email
*
* @return $this
*/
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getAddress(): ?Address
{
return $this->address;
}
public function setAddress(Address $address): self
{
$this->address = $address;
return $this;
}
public function getGender(): ?Gender
{
return $this->gender;
}
public function setGender(?Gender $gender): self
{
$this->gender = $gender;
return $this;
}
/**
* A visual identifier that represents this user.
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->professionalEmail;
}
/**
*
* @deprecated since Symfony 5.3, use getUserIdentifier instead
*/
public function getUsername(): string
{
return (string) $this->professionalEmail;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
// $roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
/**
* @param string $password
* @return $this
*/
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* @see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
$this->plainPassword = null;
}
/**
* @return string|null
*/
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
/**
* @param string $plainPassword
*
* @return $this
*/
public function setPlainPassword(string $plainPassword): self
{
$this->plainPassword = $plainPassword;
return $this;
}
public function getProfessionalEmail(): ?string
{
return $this->professionalEmail;
}
public function setProfessionalEmail(string $professionalEmail): self
{
$this->professionalEmail = $professionalEmail;
return $this;
}
public function getReferenceStatus(): ?ReferenceCollaboratorStatus
{
return $this->referenceStatus;
}
public function setReferenceStatus(?ReferenceCollaboratorStatus $referenceStatus): self
{
$this->referenceStatus = $referenceStatus;
return $this;
}
public function getReferenceMaritalStatus(): ?ReferencePersonMaritalStatus
{
return $this->referenceMaritalStatus;
}
public function setReferenceMaritalStatus(?ReferencePersonMaritalStatus $referenceMaritalStatus): self
{
$this->referenceMaritalStatus = $referenceMaritalStatus;
return $this;
}
/**
* @param int|null $id
*
* @return $this
*/
public function setId(?int $id): self
{
$this->id = $id;
return $this;
}
public function getAvatar(): ?Avatar
{
return $this->avatar;
}
public function getFullPathAvatar(): ?string
{
return $this->avatar ? Avatar::AVATAR_PATH . $this->avatar->getFilePath() : null;
}
public function setAvatar(?Avatar $avatar): self
{
// unset the owning side of the relation if necessary
if ($avatar === null && $this->avatar !== null) {
$this->avatar->setCollaborator(null);
}
// set the owning side of the relation if necessary
if ($avatar !== null && $avatar->getCollaborator() !== $this) {
$avatar->setCollaborator($this);
}
$this->avatar = $avatar;
return $this;
}
/**
* @SerializedName("currency")
* @Groups({
* "agent:read",
* "abstract-collaborator:read",
* })
*/
public function getCurrency(): ?string
{
$country = $this->getAddress()->getCity()->getCountry();
return $country->getCurrency() ?
$country->getCurrency()->getSymbol() :
Currency::DEFAULT_CURRENCY;
}
public function getLastConnection(): ?\DateTimeInterface
{
return $this->lastConnection;
}
public function setLastConnection(?\DateTimeInterface $lastConnection): self
{
$this->lastConnection = $lastConnection;
return $this;
}
public function getCgu(): ?Cgu
{
return $this->cgu;
}
public function setCgu(Cgu $cgu): self
{
// set the owning side of the relation if necessary
if ($cgu->getCollaborator() !== $this) {
$cgu->setCollaborator($this);
}
$this->cgu = $cgu;
return $this;
}
/**
* @return string
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "prescriber:read",
* "genealogy:read",
* "mandate:read",
* "property:read",
* "agent:read","siege:put","siege:write",
* "transaction-item:read",
* "transaction:collection:read",
* "business-indication:item:read",
* "business-indication:collection:read",
* "manager:read",
* "agent:light"
* })
*/
public function getFullName(): string
{
if (null === $this->firstName && null === $this->lastName) {
return '';
}
return sprintf('%s %s', ucfirst($this->firstName), strtoupper($this->lastName));
}
public function getPersonType(): ?string
{
return $this->personType;
}
public function setPersonType(?string $personType): self
{
$this->personType = $personType;
return $this;
}
/**
* @return PersonTypeReference|null
*
* @Groups({
* "abstract-collaborator:read",
* "directory:collaborator:search",
* "candidate:read",
* "contact:read",
* "prescriber:read",
* "genealogy:read",
* "mandate:read",
* "property:read",
* "agent:read",
* "transaction-item:read",
* "transaction:collection:read",
* "business-indication:item:read",
* "business-indication:collection:read",
* "manager:read"
* })
*
* @SerializedName("personType")
*/
public function getReferencePersonType(): ?PersonTypeReference
{
if (null === $this->personType) {
return null;
}
return PersonTypeReference::createFromCode($this->getPersonType());
}
/**
* @SerializedName("isAgentConstellationHead")
*
* @Groups({"milkiya:read"})
*
* @return bool|null
*
*/
public function isAgentConstellationHead(): ?bool
{
return in_array(self::ROLE_CONSTELLATION_HEAD, $this->getRoles(), true);
}
}