<?php
namespace App\Entity;
use App\Repository\WorkerActivitiesRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\PersistentCollection;
use phpDocumentor\Reflection\Types\This;
use Monolog\DateTimeImmutable;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use function PHPUnit\Framework\returnArgument;
use Symfony\Component\Serializer\Annotation\Groups;
// Criteria olustur...
use Doctrine\Common\Collections\Criteria;
/**
* @ORM\Entity(repositoryClass=WorkerActivitiesRepository::class)
*/
class WorkerActivities
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({
* "worker.activity.core", "worker_activity@core",
* "customer.smart.active.employees",
* "worker.manage.base",
* "worker.actually.activity",
* "timesheet.for.stakeholder",
* "timesheet.for.customer",
* "customer.selected.project",
*
* "timesheet.collected.base",
*
* "worker.in.project.worker.activity.base",
*
*
* "worker.activity.substitution.worker.activity.core"
* })
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Worker::class, inversedBy="workerActivities" )
* // INFO Since cascade={"remove"} ignores the foreign key references by explicitly deleting the record.
* @ORM\JoinColumn(nullable=true, onDelete="CASCADE")
* @Groups({
* "customer.smart.active.employees",
* "worker.manage.base",
* "timesheet.for.stakeholder",
* "timesheet.for.customer",
* "customer.selected.project",
*
* "timesheet.collected.base",
*
* "worker.in.project.worker.activity.worker",
*
* "worker.activity.substitution.worker.activity.worker",
*
* "worker.activity.worker",
*
* "worker_activity@worker",
*
* })
* @ORM\OrderBy({"name" = "ASC"})
*/
private $worker;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "customer.smart.active.employees",
* "worker.manage.base",
* "worker.actually.activity",
*
* "worker.activity.core",
*
* "worker_activity@core"
* })
*/
private $entry_at;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "customer.smart.active.employees",
* "worker.manage.base",
* "worker.actually.activity",
*
* "worker.activity.core",
*
* "worker_activity@core"
* })
*/
private $exit_at;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "worker_activity@core"
* })
*/
private $created_at;
/**
* @ORM\ManyToOne(targetEntity=Customer::class, inversedBy="workerActivities")
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Groups({
* "worker.actually.activity",
* "timesheet.for.stakeholder",
* "customer.selected.project",
*
* "worker.in.project.worker.activity.customer",
*
* "worker.activity.customer",
*
* "worker_activity@customer"
*
*
* })
*/
private $customer;
/**
* @Groups({"customer.smart.active.employees", "worker.manage.base" })
*/
private $editable;
/**
* @Groups({"customer.smart.active.employees", "worker.manage.base"})
*/
private $status;
/**
* @deprecated use timesheets instead
* @ORM\OneToMany(targetEntity=WorkerTimesheet::class, mappedBy="worker_activity")
*
* @Groups({
* "worker.manage.base.timesheet",
* "timesheet.for.stakeholder",
* "timesheet.for.customer",
*
* "project.joined.stakeholder.worker.in.project.worker.activity.timesheet",
*
*
*
* })
*/
private $worker_timesheets;
/**
* @ORM\OneToMany(targetEntity=WorkerInProject::class, mappedBy="worker_activity", orphanRemoval=true, fetch="EXTRA_LAZY")
* @ORM\OrderBy({"id":"DESC"})
* @Groups({"worker.manage.base", "worker.manage.joined.projects"})
*
*/
private $worker_in_projects;
/**
* @ORM\Column(type="boolean", nullable=true)
* @Groups({
* "worker.manage.base",
* "customer.smart.active.employees",
* "timesheet.for.stakeholder",
* })
*/
private $guest;
/**
* @ORM\OneToMany(targetEntity=WorkerTimesheetPayments::class, mappedBy="worker_activity", orphanRemoval=true, cascade={"persist", "remove"} )
* @Groups({"worker.manage.base.timesheet.payments"})
*/
private $worker_timesheet_payments;
/**
* TODO this should be in WorkerActivities
* @ORM\OneToMany(targetEntity=ProjectOrders::class, mappedBy="order_primary_lead")
*/
private $projectOrders;
/**
*
* Bu yapı, WorkerActivities (İşçi Aktiviteleri) tablosunda bir aktivitenin başka bir aktiviteyle ilişkili
* olduğunu belirtmek için kullanılır.
* Bu, özellikle bir işçinin yokluğunda onun yerine geçen başka bir işçinin aktivitesini takip etmek için
* faydalıdır.
*
* 🧱 Teknik Açıklama
* ManyToMany İlişki: Bir aktivite birden fazla aktiviteyle ilişkili olabilir ve tersi de geçerlidir.
* Self-Referencing: İlişki aynı tablo (WorkerActivities) içinde tanımlanmıştır.
* JoinTable: İlişkiyi temsil eden ara tablo manuel olarak adlandırılmıştır: worker_activity_substitutions.
* joinColumns: İlişkinin sahibi olan aktiviteyi belirtir.
* inverseJoinColumns: İlişkinin hedefi olan aktiviteyi belirtir.
*
* This property defines the activities that this activity *replaces* or *substitutes*.
*
* In other words, if a worker cannot perform their original activity (e.g., due to absence),
* this activity can take over those responsibilities. This allows tracking which activities
* serve as substitutes for others.
*
* The relationship is many-to-many and self-referencing within the WorkerActivities entity.
*
* For example:
* - Activity A substitutes Activity B and C.
* - Activity B is substituted by Activity A.
*
* This is the owning side of the relation.
* @MaxDepth(1)
* @ORM\ManyToMany(targetEntity=WorkerActivities::class, inversedBy="worker_substituted_activities")
* @ORM\JoinTable(
* name="worker_activity_substitutions",
* joinColumns={@ORM\JoinColumn(name="main_activity_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="substituted_activity_id", referencedColumnName="id")}
* )
* @Groups({
* "worker.activity.substitutions",
* })
*/
private $worker_activity_substitutions;
/**
* @MaxDepth(1)
* @ORM\ManyToMany(targetEntity=WorkerActivities::class, mappedBy="worker_activity_substitutions")
* @Groups({
* "worker.activity.coverages",
* })
*/
private $worker_substituted_activities;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="worker_activities")
* @Groups({
* "worker.activity.user"
* })
* @ORM\JoinColumn(onDelete="SET NULL")
*/
private $user;
/**
* @ORM\Column(type="boolean", nullable=true, options={"comment": "Indicates whether the worker is accountable for the profitability performance of the Aufträge they participated in. If true, the worker's success/failure will be evaluated based on whether the project met its profit margin targets. ( Bu işçinin görev aldığı Aufträg'ların kâr hedefine ulaşıp ulaşmamasıyla ilişkilendirilmesini sağlayan bilgi alanı.)"} )
* @Groups({
* "worker.manage.base",
* "worker.activity.core", "worker_activity@core",
* "customer.smart.active.employees",
*
* "worker_activity@core"
* })
*/
private $is_kpi_responsible;
/**
* @ORM\ManyToMany(targetEntity=ProjectOrders::class, mappedBy="assigned_workers")
*/
private $assigned_orders;
/**
* @ORM\OneToMany(targetEntity=Timesheets::class, mappedBy="worker_activity", orphanRemoval=true)
*/
private $timesheets;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Groups({
* "worker.activity.core",
*
* "worker_activity@core"
* })
*
*/
private $termination_reason;
// /**
// * Private param
// * @Groups({
// * "worker.last.activity",
// * })
// */
// private $last_activity;
//
// /**
// * @return mixed
// */
// public function getLastActivity()
// {
// $criteria = Criteria::create();
// $criteria->orderBy(['created_at' => Criteria::DESC])->setMaxResults(1);
//
// /**@var WorkerActivities $latestActivity*/
// $latestActivity = $this->getWorker()->getWorkerActivities()->matching($criteria)->first();
//
// #dd(334);
// return $latestActivity->getId() ?? null;
//
//// $all_activities = $this->getWorker()->getWorkerActivities()->toArray();
//// usort($all_activities, fn($a, $b) => $b['created_at'] <=> $a['created_at']); // ID'ye göre azalan sıralama
//// return $all_activities[0] ?? null; // ID'si en büyük olan
// }
public function __construct()
{
$this->worker_timesheets = new ArrayCollection();
$this->worker_in_projects = new ArrayCollection();
$this->worker_timesheet_payments = new ArrayCollection();
$this->projectOrders = new ArrayCollection();
$this->worker_activity_substitutions = new ArrayCollection();
$this->worker_substituted_activities = new ArrayCollection();
$this->assigned_orders = new ArrayCollection();
$this->timesheets = new ArrayCollection();;
}
/**
* @Groups("customer.workers.smart.list")
*/
public function getEditable(): bool {
return !($this->getExitAt() && $this->getExitAt() < new \DateTimeImmutable('now'));;
}
public function getStatus(): ?array {
if( !$this->getEntryAt() && !$this->getExitAt() ){
return [
'status' => 'unknown',
'color' => 'yellow',
'message' => 'Unknown status'
];
} else if( $this->getEntryAt() && !$this->getExitAt() ){
return [
'status' => 'active',
'color' => 'green',
'message' => "Active since " . (new DateTimeImmutable('now'))->diff( $this->getEntryAt())->days . ' day(s)'
];
}
else {
$today = new \DateTimeImmutable('now');
$exitAt = $this->getExitAt();
if( $exitAt && $today < $exitAt ){
$restDay = $exitAt->diff( $today )->days;
if( !$restDay ){
return [
'status' => 'inactive',
'color' => 'red',
'message' => "Inactive in " . $exitAt->diff( $today )->h . " Hour(s)"
];
}
return [
'status' => 'inactive',
'color' => 'red',
'message' => "Inactive in " . $restDay . " Day(s)"
];
}
}
return [
'status' => 'inactive',
'color' => 'red',
'message' => "Inactive since " . (new DateTimeImmutable('now'))->diff( $this->getExitAt())->days . ' day(s)'
];
}
public function getCompanyName(): ?string{
return $this->getCustomer()->getCompany();
}
public function getId(): ?int
{
return $this->id;
}
public function getWorker(): ?Worker
{
return $this->worker;
}
public function setWorker(?Worker $worker): self
{
$this->worker = $worker;
return $this;
}
public function getEntryAt(): ?\DateTimeImmutable
{
return $this->entry_at;
}
public function setEntryAt(?\DateTimeImmutable $entry_at): self
{
$this->entry_at = $entry_at;
return $this;
}
public function getExitAt(): ?\DateTimeImmutable
{
return $this->exit_at;
}
public function setExitAt(?\DateTimeImmutable $exit_at): self
{
$this->exit_at = $exit_at;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->created_at;
}
public function setCreatedAt(?\DateTimeImmutable $created_at): self
{
$this->created_at = $created_at;
return $this;
}
public function getCustomer(): ?Customer
{
return $this->customer;
}
public function setCustomer(?Customer $customer): self
{
$this->customer = $customer;
return $this;
}
/**
* @return Collection<int, WorkerTimesheet>
*/
public function getWorkerTimesheets(): Collection
{
return $this->worker_timesheets;
}
public function addWorkerTimesheet(WorkerTimesheet $workerTimesheet): self
{
if (!$this->worker_timesheets->contains($workerTimesheet)) {
$this->worker_timesheets[] = $workerTimesheet;
$workerTimesheet->setWorkerActivity($this);
}
return $this;
}
public function removeWorkerTimesheet(WorkerTimesheet $workerTimesheet): self
{
if ($this->worker_timesheets->removeElement($workerTimesheet)) {
// set the owning side to null (unless already changed)
if ($workerTimesheet->getWorkerActivity() === $this) {
$workerTimesheet->setWorkerActivity(null);
}
}
return $this;
}
/**
* @return Collection<int, WorkerInProject>
*/
public function getWorkerInProjects(): ?Collection
{
return $this->worker_in_projects;
}
public function addWorkerInProject(WorkerInProject $workerInProject): self
{
if (!$this->worker_in_projects->contains($workerInProject)) {
$this->worker_in_projects[] = $workerInProject;
$workerInProject->setWorker($this);
}
return $this;
}
public function removeWorkerInProject(WorkerInProject $workerInProject): self
{
if ($this->worker_in_projects->removeElement($workerInProject)) {
// set the owning side to null (unless already changed)
if ($workerInProject->getWorker() === $this) {
$workerInProject->setWorker(null);
}
}
return $this;
}
public function isGuest(): ?bool
{
return $this->guest;
}
public function setGuest(?bool $guest): self
{
$this->guest = $guest;
return $this;
}
/**
* @return Collection<int, WorkerTimesheetPayments>
*/
public function getWorkerTimesheetpayments(): Collection
{
return $this->worker_timesheet_payments;
}
public function addWorkerTimesheetPayment(WorkerTimesheetPayments $workerTimesheetPayment): self
{
if (!$this->worker_timesheet_payments->contains($workerTimesheetPayment)) {
$this->worker_timesheet_payments[] = $workerTimesheetPayment;
$workerTimesheetPayment->setWorkerActivity($this);
}
return $this;
}
public function removeWorkerTimesheetPayment(WorkerTimesheetPayments $workerTimesheetPayment): self
{
if ($this->worker_timesheet_payments->removeElement($workerTimesheetPayment)) {
// set the owning side to null (unless already changed)
if ($workerTimesheetPayment->getWorkerActivity() === $this) {
$workerTimesheetPayment->setWorkerActivity(null);
}
}
return $this;
}
/**
* @return Collection<int, ProjectOrders>
*/
public function getProjectOrders(): Collection
{
return $this->projectOrders;
}
public function addProjectOrder(ProjectOrders $projectOrder): self
{
if (!$this->projectOrders->contains($projectOrder)) {
$this->projectOrders[] = $projectOrder;
$projectOrder->setOrderLead($this);
}
return $this;
}
public function removeProjectOrder(ProjectOrders $projectOrder): self
{
if ($this->projectOrders->removeElement($projectOrder)) {
// set the owning side to null (unless already changed)
if ($projectOrder->getOrderLead() === $this) {
$projectOrder->setOrderLead(null);
}
}
return $this;
}
/**
* @return Collection<int, self>
*/
public function getWorkerActivitySubstitutions(): Collection
{
return $this->worker_activity_substitutions;
}
public function addWorkerSubstitutedActivity(self $workerSubstitutedActivity): self
{
if (!$this->worker_activity_substitutions->contains($workerSubstitutedActivity)) {
$this->worker_activity_substitutions[] = $workerSubstitutedActivity;
}
return $this;
}
public function removeWorkerSubstitutedActivity(self $workerSubstitutedActivity): self
{
$this->worker_activity_substitutions->removeElement($workerSubstitutedActivity);
return $this;
}
/**
* @return Collection<int, self>
*/
public function getWorkerSubstitutedActivities(): Collection
{
return $this->worker_substituted_activities;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function isIsKpiResponsible(): ?bool
{
return $this->is_kpi_responsible;
}
public function setIsKpiResponsible(?bool $is_kpi_responsible): self
{
$this->is_kpi_responsible = $is_kpi_responsible;
return $this;
}
/**
* @return Collection<int, ProjectOrders>
*/
public function getAssignedOrders(): Collection
{
return $this->assigned_orders;
}
public function addAssignedOrder(ProjectOrders $assignedOrder): self
{
if (!$this->assigned_orders->contains($assignedOrder)) {
$this->assigned_orders[] = $assignedOrder;
$assignedOrder->addAssignedWorker($this);
}
return $this;
}
public function removeAssignedOrder(ProjectOrders $assignedOrder): self
{
if ($this->assigned_orders->removeElement($assignedOrder)) {
$assignedOrder->removeAssignedWorker($this);
}
return $this;
}
/**
* @return Collection<int, Timesheets>
*/
public function getTimesheets(): Collection
{
return $this->timesheets;
}
public function addTimesheet(Timesheets $timesheet): self
{
if (!$this->timesheets->contains($timesheet)) {
$this->timesheets[] = $timesheet;
$timesheet->setWorkerActivity($this);
}
return $this;
}
public function removeTimesheet(Timesheets $timesheet): self
{
if ($this->timesheets->removeElement($timesheet)) {
// set the owning side to null (unless already changed)
if ($timesheet->getWorkerActivity() === $this) {
$timesheet->setWorkerActivity(null);
}
}
return $this;
}
public function getTerminationReason(): ?string
{
return $this->termination_reason;
}
public function setTerminationReason(?string $termination_reason): self
{
$this->termination_reason = $termination_reason;
return $this;
}
}