src/Entity/WorkerActivities.php line 22

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\WorkerActivitiesRepository;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Collection;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Doctrine\ORM\PersistentCollection;
  8. use phpDocumentor\Reflection\Types\This;
  9. use Monolog\DateTimeImmutable;
  10. use Symfony\Component\Serializer\Annotation\MaxDepth;
  11. use function PHPUnit\Framework\returnArgument;
  12. use Symfony\Component\Serializer\Annotation\Groups;
  13. // Criteria olustur...
  14. use Doctrine\Common\Collections\Criteria;
  15. /**
  16.  * @ORM\Entity(repositoryClass=WorkerActivitiesRepository::class)
  17.  */
  18. class WorkerActivities
  19. {
  20.     /**
  21.      * @ORM\Id
  22.      * @ORM\GeneratedValue
  23.      * @ORM\Column(type="integer")
  24.      * @Groups({
  25.      *      "worker.activity.core", "worker_activity@core",
  26.      *      "customer.smart.active.employees",
  27.      *      "worker.manage.base",
  28.      *      "worker.actually.activity",
  29.      *      "timesheet.for.stakeholder",
  30.      *      "timesheet.for.customer",
  31.      *      "customer.selected.project",
  32.      *
  33.      *      "timesheet.collected.base",
  34.      *
  35.      *      "worker.in.project.worker.activity.base",
  36.      *
  37.      *
  38.      *      "worker.activity.substitution.worker.activity.core"
  39.      * })
  40.      */
  41.     private $id;
  42.     /**
  43.      * @ORM\ManyToOne(targetEntity=Worker::class, inversedBy="workerActivities" )
  44.      * // INFO Since cascade={"remove"} ignores the foreign key references by explicitly deleting the record.
  45.      * @ORM\JoinColumn(nullable=true, onDelete="CASCADE")
  46.      * @Groups({
  47.      *     "customer.smart.active.employees",
  48.      *     "worker.manage.base",
  49.      *     "timesheet.for.stakeholder",
  50.      *     "timesheet.for.customer",
  51.      *     "customer.selected.project",
  52.      *
  53.      *     "timesheet.collected.base",
  54.      *
  55.      *     "worker.in.project.worker.activity.worker",
  56.      *
  57.      *     "worker.activity.substitution.worker.activity.worker",
  58.      *
  59.      *     "worker.activity.worker",
  60.      *
  61.      *     "worker_activity@worker",
  62.      *
  63.      *     })
  64.      * @ORM\OrderBy({"name" = "ASC"})
  65.      */
  66.     private $worker;
  67.     /**
  68.      * @ORM\Column(type="datetime_immutable", nullable=true)
  69.      * @Groups({
  70.      *     "customer.smart.active.employees",
  71.      *     "worker.manage.base",
  72.      *     "worker.actually.activity",
  73.      *
  74.      *     "worker.activity.core",
  75.      *
  76.      *     "worker_activity@core"
  77.      * })
  78.      */
  79.     private $entry_at;
  80.     /**
  81.      * @ORM\Column(type="datetime_immutable", nullable=true)
  82.      * @Groups({
  83.      *     "customer.smart.active.employees",
  84.      *     "worker.manage.base",
  85.      *     "worker.actually.activity",
  86.      *
  87.      *     "worker.activity.core",
  88.      *
  89.      *      "worker_activity@core"
  90.      * })
  91.      */
  92.     private $exit_at;
  93.     /**
  94.      * @ORM\Column(type="datetime_immutable", nullable=true)
  95.      * @Groups({
  96.      *     "worker_activity@core"
  97.      * })
  98.      */
  99.     private $created_at;
  100.     /**
  101.      * @ORM\ManyToOne(targetEntity=Customer::class, inversedBy="workerActivities")
  102.      * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
  103.      * @Groups({
  104.      *     "worker.actually.activity",
  105.      *     "timesheet.for.stakeholder",
  106.      *     "customer.selected.project",
  107.      *
  108.      *     "worker.in.project.worker.activity.customer",
  109.      *
  110.      *     "worker.activity.customer",
  111.      *
  112.      *     "worker_activity@customer"
  113.      *
  114.      *
  115.      *     })
  116.      */
  117.     private $customer;
  118.     /**
  119.      * @Groups({"customer.smart.active.employees", "worker.manage.base" })
  120.     */
  121.     private $editable;
  122.     /**
  123.      * @Groups({"customer.smart.active.employees", "worker.manage.base"})
  124.     */
  125.     private $status;
  126.     /**
  127.      * @deprecated use timesheets instead
  128.      * @ORM\OneToMany(targetEntity=WorkerTimesheet::class, mappedBy="worker_activity")
  129.      *
  130.      * @Groups({
  131.      *       "worker.manage.base.timesheet",
  132.      *       "timesheet.for.stakeholder",
  133.      *       "timesheet.for.customer",
  134.      *
  135.      *       "project.joined.stakeholder.worker.in.project.worker.activity.timesheet",
  136.      *
  137.      *
  138.      *
  139.      *       })
  140.      */
  141.     private $worker_timesheets;
  142.     /**
  143.      * @ORM\OneToMany(targetEntity=WorkerInProject::class, mappedBy="worker_activity", orphanRemoval=true, fetch="EXTRA_LAZY")
  144.      * @ORM\OrderBy({"id":"DESC"})
  145.      * @Groups({"worker.manage.base", "worker.manage.joined.projects"})
  146.      *
  147.      */
  148.     private $worker_in_projects;
  149.     /**
  150.      * @ORM\Column(type="boolean", nullable=true)
  151.      * @Groups({
  152.      *     "worker.manage.base",
  153.      *     "customer.smart.active.employees",
  154.      *     "timesheet.for.stakeholder",
  155.      *     })
  156.      */
  157.     private $guest;
  158.     /**
  159.      * @ORM\OneToMany(targetEntity=WorkerTimesheetPayments::class, mappedBy="worker_activity", orphanRemoval=true, cascade={"persist", "remove"} )
  160.      * @Groups({"worker.manage.base.timesheet.payments"})
  161.      */
  162.     private $worker_timesheet_payments;
  163.     /**
  164.      * TODO this should be in WorkerActivities
  165.      * @ORM\OneToMany(targetEntity=ProjectOrders::class, mappedBy="order_primary_lead")
  166.      */
  167.     private $projectOrders;
  168.     /**
  169.      *
  170.      *      Bu yapı, WorkerActivities (İşçi Aktiviteleri) tablosunda bir aktivitenin başka bir aktiviteyle ilişkili
  171.      *      olduğunu belirtmek için kullanılır.
  172.      *      Bu, özellikle bir işçinin yokluğunda onun yerine geçen başka bir işçinin aktivitesini takip etmek için
  173.      *      faydalıdır.
  174.      *
  175.      * 🧱   Teknik Açıklama
  176.      *      ManyToMany İlişki: Bir aktivite birden fazla aktiviteyle ilişkili olabilir ve tersi de geçerlidir.
  177.      *      Self-Referencing: İlişki aynı tablo (WorkerActivities) içinde tanımlanmıştır.
  178.      *      JoinTable: İlişkiyi temsil eden ara tablo manuel olarak adlandırılmıştır: worker_activity_substitutions.
  179.      *      joinColumns: İlişkinin sahibi olan aktiviteyi belirtir.
  180.      *      inverseJoinColumns: İlişkinin hedefi olan aktiviteyi belirtir.
  181.      *
  182.      *      This property defines the activities that this activity *replaces* or *substitutes*.
  183.      *
  184.      *      In other words, if a worker cannot perform their original activity (e.g., due to absence),
  185.      *      this activity can take over those responsibilities. This allows tracking which activities
  186.      *      serve as substitutes for others.
  187.      *
  188.      *      The relationship is many-to-many and self-referencing within the WorkerActivities entity.
  189.      *
  190.      *      For example:
  191.      *      - Activity A substitutes Activity B and C.
  192.      *      - Activity B is substituted by Activity A.
  193.      *
  194.      *      This is the owning side of the relation.
  195.      * @MaxDepth(1)
  196.      * @ORM\ManyToMany(targetEntity=WorkerActivities::class, inversedBy="worker_substituted_activities")
  197.      * @ORM\JoinTable(
  198.      *      name="worker_activity_substitutions",
  199.      *      joinColumns={@ORM\JoinColumn(name="main_activity_id", referencedColumnName="id")},
  200.      *      inverseJoinColumns={@ORM\JoinColumn(name="substituted_activity_id", referencedColumnName="id")}
  201.      *  )
  202.      * @Groups({
  203.      *        "worker.activity.substitutions",
  204.      *    })
  205.     */
  206.     private $worker_activity_substitutions;
  207.     /**
  208.      * @MaxDepth(1)
  209.      * @ORM\ManyToMany(targetEntity=WorkerActivities::class, mappedBy="worker_activity_substitutions")
  210.      * @Groups({
  211.      *          "worker.activity.coverages",
  212.      * })
  213.      */
  214.     private $worker_substituted_activities;
  215.     /**
  216.      * @ORM\ManyToOne(targetEntity=User::class, inversedBy="worker_activities")
  217.      * @Groups({
  218.      *     "worker.activity.user"
  219.      *     })
  220.      * @ORM\JoinColumn(onDelete="SET NULL")
  221.      */
  222.     private $user;
  223.     /**
  224.      * @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ı.)"} )
  225.      * @Groups({
  226.      *     "worker.manage.base",
  227.      *     "worker.activity.core", "worker_activity@core",
  228.      *     "customer.smart.active.employees",
  229.      *
  230.      *     "worker_activity@core"
  231.      * })
  232.      */
  233.     private $is_kpi_responsible;
  234.     /**
  235.      * @ORM\ManyToMany(targetEntity=ProjectOrders::class, mappedBy="assigned_workers")
  236.      */
  237.     private $assigned_orders;
  238.     /**
  239.      * @ORM\OneToMany(targetEntity=Timesheets::class, mappedBy="worker_activity", orphanRemoval=true)
  240.      */
  241.     private $timesheets;
  242.     /**
  243.      * @ORM\Column(type="string", length=255, nullable=true)
  244.      * @Groups({
  245.      *      "worker.activity.core",
  246.      *
  247.      *      "worker_activity@core"
  248.      *  })
  249.      *
  250.      */
  251.     private $termination_reason;
  252. //    /**
  253. //     * Private param
  254. //     * @Groups({
  255. //     *           "worker.last.activity",
  256. //     *  })
  257. //     */
  258. //    private $last_activity;
  259. //
  260. //    /**
  261. //     * @return mixed
  262. //     */
  263. //    public function getLastActivity()
  264. //    {
  265. //        $criteria = Criteria::create();
  266. //        $criteria->orderBy(['created_at' => Criteria::DESC])->setMaxResults(1);
  267. //
  268. //        /**@var WorkerActivities $latestActivity*/
  269. //        $latestActivity = $this->getWorker()->getWorkerActivities()->matching($criteria)->first();
  270. //
  271. //        #dd(334);
  272. //        return $latestActivity->getId() ?? null;
  273. //
  274. ////        $all_activities = $this->getWorker()->getWorkerActivities()->toArray();
  275. ////        usort($all_activities, fn($a, $b) => $b['created_at'] <=> $a['created_at']); // ID'ye göre azalan sıralama
  276. ////        return $all_activities[0] ?? null; // ID'si en büyük olan
  277. //    }
  278.     public function __construct()
  279.     {
  280.         $this->worker_timesheets = new ArrayCollection();
  281.         $this->worker_in_projects = new ArrayCollection();
  282.         $this->worker_timesheet_payments = new ArrayCollection();
  283.         $this->projectOrders = new ArrayCollection();
  284.         $this->worker_activity_substitutions = new ArrayCollection();
  285.         $this->worker_substituted_activities = new ArrayCollection();
  286.         $this->assigned_orders = new ArrayCollection();
  287.         $this->timesheets = new ArrayCollection();;
  288.     }
  289.     /**
  290.      * @Groups("customer.workers.smart.list")
  291.     */
  292.     public function getEditable(): bool {
  293.         return !($this->getExitAt() && $this->getExitAt() < new \DateTimeImmutable('now'));;
  294.     }
  295.     public function getStatus(): ?array {
  296.         if( !$this->getEntryAt() && !$this->getExitAt() ){
  297.             return [
  298.                 'status' => 'unknown',
  299.                 'color' => 'yellow',
  300.                 'message' => 'Unknown status'
  301.             ];
  302.         } else if( $this->getEntryAt() && !$this->getExitAt() ){
  303.             return [
  304.                 'status' => 'active',
  305.                 'color' => 'green',
  306.                 'message' => "Active since " . (new DateTimeImmutable('now'))->diff$this->getEntryAt())->days ' day(s)'
  307.             ];
  308.         }
  309.         else {
  310.             $today = new \DateTimeImmutable('now');
  311.             $exitAt $this->getExitAt();
  312.             if( $exitAt && $today $exitAt ){
  313.                 $restDay $exitAt->diff$today )->days;
  314.                 if( !$restDay ){
  315.                     return [
  316.                         'status' => 'inactive',
  317.                         'color' => 'red',
  318.                         'message' => "Inactive in " $exitAt->diff$today )->" Hour(s)"
  319.                     ];
  320.                 }
  321.                 return [
  322.                     'status' => 'inactive',
  323.                     'color' => 'red',
  324.                     'message' => "Inactive in " $restDay " Day(s)"
  325.                 ];
  326.             }
  327.         }
  328.         return [
  329.             'status' => 'inactive',
  330.             'color' => 'red',
  331.             'message' => "Inactive since " . (new DateTimeImmutable('now'))->diff$this->getExitAt())->days ' day(s)'
  332.         ];
  333.     }
  334.     public function getCompanyName(): ?string{
  335.         return $this->getCustomer()->getCompany();
  336.     }
  337.     public function getId(): ?int
  338.     {
  339.         return $this->id;
  340.     }
  341.     public function getWorker(): ?Worker
  342.     {
  343.         return $this->worker;
  344.     }
  345.     public function setWorker(?Worker $worker): self
  346.     {
  347.         $this->worker $worker;
  348.         return $this;
  349.     }
  350.     public function getEntryAt(): ?\DateTimeImmutable
  351.     {
  352.         return $this->entry_at;
  353.     }
  354.     public function setEntryAt(?\DateTimeImmutable $entry_at): self
  355.     {
  356.         $this->entry_at $entry_at;
  357.         return $this;
  358.     }
  359.     public function getExitAt(): ?\DateTimeImmutable
  360.     {
  361.         return $this->exit_at;
  362.     }
  363.     public function setExitAt(?\DateTimeImmutable $exit_at): self
  364.     {
  365.         $this->exit_at $exit_at;
  366.         return $this;
  367.     }
  368.     public function getCreatedAt(): ?\DateTimeImmutable
  369.     {
  370.         return $this->created_at;
  371.     }
  372.     public function setCreatedAt(?\DateTimeImmutable $created_at): self
  373.     {
  374.         $this->created_at $created_at;
  375.         return $this;
  376.     }
  377.     public function getCustomer(): ?Customer
  378.     {
  379.         return $this->customer;
  380.     }
  381.     public function setCustomer(?Customer $customer): self
  382.     {
  383.         $this->customer $customer;
  384.         return $this;
  385.     }
  386.     /**
  387.      * @return Collection<int, WorkerTimesheet>
  388.      */
  389.     public function getWorkerTimesheets(): Collection
  390.     {
  391.         return $this->worker_timesheets;
  392.     }
  393.     public function addWorkerTimesheet(WorkerTimesheet $workerTimesheet): self
  394.     {
  395.         if (!$this->worker_timesheets->contains($workerTimesheet)) {
  396.             $this->worker_timesheets[] = $workerTimesheet;
  397.             $workerTimesheet->setWorkerActivity($this);
  398.         }
  399.         return $this;
  400.     }
  401.     public function removeWorkerTimesheet(WorkerTimesheet $workerTimesheet): self
  402.     {
  403.         if ($this->worker_timesheets->removeElement($workerTimesheet)) {
  404.             // set the owning side to null (unless already changed)
  405.             if ($workerTimesheet->getWorkerActivity() === $this) {
  406.                 $workerTimesheet->setWorkerActivity(null);
  407.             }
  408.         }
  409.         return $this;
  410.     }
  411.     /**
  412.      * @return Collection<int, WorkerInProject>
  413.      */
  414.     public function getWorkerInProjects(): ?Collection
  415.     {
  416.         return $this->worker_in_projects;
  417.     }
  418.     public function addWorkerInProject(WorkerInProject $workerInProject): self
  419.     {
  420.         if (!$this->worker_in_projects->contains($workerInProject)) {
  421.             $this->worker_in_projects[] = $workerInProject;
  422.             $workerInProject->setWorker($this);
  423.         }
  424.         return $this;
  425.     }
  426.     public function removeWorkerInProject(WorkerInProject $workerInProject): self
  427.     {
  428.         if ($this->worker_in_projects->removeElement($workerInProject)) {
  429.             // set the owning side to null (unless already changed)
  430.             if ($workerInProject->getWorker() === $this) {
  431.                 $workerInProject->setWorker(null);
  432.             }
  433.         }
  434.         return $this;
  435.     }
  436.     public function isGuest(): ?bool
  437.     {
  438.         return $this->guest;
  439.     }
  440.     public function setGuest(?bool $guest): self
  441.     {
  442.         $this->guest $guest;
  443.         return $this;
  444.     }
  445.     /**
  446.      * @return Collection<int, WorkerTimesheetPayments>
  447.      */
  448.     public function getWorkerTimesheetpayments(): Collection
  449.     {
  450.         return $this->worker_timesheet_payments;
  451.     }
  452.     public function addWorkerTimesheetPayment(WorkerTimesheetPayments $workerTimesheetPayment): self
  453.     {
  454.         if (!$this->worker_timesheet_payments->contains($workerTimesheetPayment)) {
  455.             $this->worker_timesheet_payments[] = $workerTimesheetPayment;
  456.             $workerTimesheetPayment->setWorkerActivity($this);
  457.         }
  458.         return $this;
  459.     }
  460.     public function removeWorkerTimesheetPayment(WorkerTimesheetPayments $workerTimesheetPayment): self
  461.     {
  462.         if ($this->worker_timesheet_payments->removeElement($workerTimesheetPayment)) {
  463.             // set the owning side to null (unless already changed)
  464.             if ($workerTimesheetPayment->getWorkerActivity() === $this) {
  465.                 $workerTimesheetPayment->setWorkerActivity(null);
  466.             }
  467.         }
  468.         return $this;
  469.     }
  470.     /**
  471.      * @return Collection<int, ProjectOrders>
  472.      */
  473.     public function getProjectOrders(): Collection
  474.     {
  475.         return $this->projectOrders;
  476.     }
  477.     public function addProjectOrder(ProjectOrders $projectOrder): self
  478.     {
  479.         if (!$this->projectOrders->contains($projectOrder)) {
  480.             $this->projectOrders[] = $projectOrder;
  481.             $projectOrder->setOrderLead($this);
  482.         }
  483.         return $this;
  484.     }
  485.     public function removeProjectOrder(ProjectOrders $projectOrder): self
  486.     {
  487.         if ($this->projectOrders->removeElement($projectOrder)) {
  488.             // set the owning side to null (unless already changed)
  489.             if ($projectOrder->getOrderLead() === $this) {
  490.                 $projectOrder->setOrderLead(null);
  491.             }
  492.         }
  493.         return $this;
  494.     }
  495.     /**
  496.      * @return Collection<int, self>
  497.      */
  498.     public function getWorkerActivitySubstitutions(): Collection
  499.     {
  500.         return $this->worker_activity_substitutions;
  501.     }
  502.     public function addWorkerSubstitutedActivity(self $workerSubstitutedActivity): self
  503.     {
  504.         if (!$this->worker_activity_substitutions->contains($workerSubstitutedActivity)) {
  505.             $this->worker_activity_substitutions[] = $workerSubstitutedActivity;
  506.         }
  507.         return $this;
  508.     }
  509.     public function removeWorkerSubstitutedActivity(self $workerSubstitutedActivity): self
  510.     {
  511.         $this->worker_activity_substitutions->removeElement($workerSubstitutedActivity);
  512.         return $this;
  513.     }
  514.     /**
  515.      * @return Collection<int, self>
  516.      */
  517.     public function getWorkerSubstitutedActivities(): Collection
  518.     {
  519.         return $this->worker_substituted_activities;
  520.     }
  521.     public function getUser(): ?User
  522.     {
  523.         return $this->user;
  524.     }
  525.     public function setUser(?User $user): self
  526.     {
  527.         $this->user $user;
  528.         return $this;
  529.     }
  530.     public function isIsKpiResponsible(): ?bool
  531.     {
  532.         return $this->is_kpi_responsible;
  533.     }
  534.     public function setIsKpiResponsible(?bool $is_kpi_responsible): self
  535.     {
  536.         $this->is_kpi_responsible $is_kpi_responsible;
  537.         return $this;
  538.     }
  539.     /**
  540.      * @return Collection<int, ProjectOrders>
  541.      */
  542.     public function getAssignedOrders(): Collection
  543.     {
  544.         return $this->assigned_orders;
  545.     }
  546.     public function addAssignedOrder(ProjectOrders $assignedOrder): self
  547.     {
  548.         if (!$this->assigned_orders->contains($assignedOrder)) {
  549.             $this->assigned_orders[] = $assignedOrder;
  550.             $assignedOrder->addAssignedWorker($this);
  551.         }
  552.         return $this;
  553.     }
  554.     public function removeAssignedOrder(ProjectOrders $assignedOrder): self
  555.     {
  556.         if ($this->assigned_orders->removeElement($assignedOrder)) {
  557.             $assignedOrder->removeAssignedWorker($this);
  558.         }
  559.         return $this;
  560.     }
  561.     /**
  562.      * @return Collection<int, Timesheets>
  563.      */
  564.     public function getTimesheets(): Collection
  565.     {
  566.         return $this->timesheets;
  567.     }
  568.     public function addTimesheet(Timesheets $timesheet): self
  569.     {
  570.         if (!$this->timesheets->contains($timesheet)) {
  571.             $this->timesheets[] = $timesheet;
  572.             $timesheet->setWorkerActivity($this);
  573.         }
  574.         return $this;
  575.     }
  576.     public function removeTimesheet(Timesheets $timesheet): self
  577.     {
  578.         if ($this->timesheets->removeElement($timesheet)) {
  579.             // set the owning side to null (unless already changed)
  580.             if ($timesheet->getWorkerActivity() === $this) {
  581.                 $timesheet->setWorkerActivity(null);
  582.             }
  583.         }
  584.         return $this;
  585.     }
  586.     public function getTerminationReason(): ?string
  587.     {
  588.         return $this->termination_reason;
  589.     }
  590.     public function setTerminationReason(?string $termination_reason): self
  591.     {
  592.         $this->termination_reason $termination_reason;
  593.         return $this;
  594.     }
  595. }