src/Entity/ProjectOrderTaskJobs.php line 12

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\ProjectOrderTaskJobsRepository;
  4. use Doctrine\ORM\Mapping as ORM;
  5. use Symfony\Component\Serializer\Annotation\Groups;
  6. /**
  7.  * @ORM\Entity(repositoryClass=ProjectOrderTaskJobsRepository::class)
  8.  */
  9. class ProjectOrderTaskJobs
  10. {
  11.     /**
  12.      * @ORM\Id
  13.      * @ORM\GeneratedValue
  14.      * @ORM\Column(type="integer")
  15.      * @Groups({
  16.      *     "project_order_task_job@base",
  17.      *     "project_order_task_job@core"
  18.      * })
  19.      */
  20.     private $id;
  21.     /**
  22.      * @ORM\ManyToOne(targetEntity=ProjectOrderTasks::class, inversedBy="project_order_task_jobs")
  23.      * @ORM\JoinColumn(onDelete="CASCADE")
  24.      */
  25.     // TODO Replace with task $order_task > $task !!!
  26.     private $order_task;
  27.     /**
  28.      * @ORM\Column(type="float", nullable=true)
  29.      * @Groups({
  30.      *     "project_order_task_job@core"
  31.      *  })
  32.      */
  33.     private $job_weight;
  34.     /**
  35.      * @ORM\Column(type="integer")
  36.      * @Groups({
  37.      *      "project_order_task_job@core"
  38.      *   })
  39.      */
  40.     private $job_index;
  41.     /**
  42.      * @ORM\Column(type="date_immutable", nullable=true)
  43.      * @Groups({
  44.      *      "project_order_task_job@core"
  45.      *   })
  46.      */
  47.     private $start_at;
  48.     /**
  49.      * @ORM\Column(type="date_immutable", nullable=true)
  50.      * @Groups({
  51.      *       "project_order_task_job@core"
  52.      *    })
  53.      */
  54.     private $end_at;
  55.     /**
  56.      * @ORM\Column(type="float", nullable=true)
  57.      * @Groups({
  58.      *      "project_order_task_job@core"
  59.      *   })
  60.      */
  61.     private $rating;
  62.     /**
  63.      * @ORM\Column(type="integer", nullable=true)
  64.      * @Groups({
  65.      *      "project_order_task_job@core"
  66.      *   })
  67.      */
  68.     private $real_days;
  69.     /**
  70.      * @ORM\Column(type="text", nullable=true)
  71.      * @Groups({
  72.      *      "project_order_task_job@core"
  73.      *   })
  74.      */
  75.     private $job_description;
  76.     /**
  77.      * @ORM\Column(type="float", nullable=true)
  78.      * @Groups({
  79.      *        "project_order_task_job@core"
  80.      *     })
  81.      */
  82.     private $duration_days;
  83.     /**
  84.      * TaskExecution — servisin job'a yazdigi ilerleme notu (K5: yayin sonrasi
  85.      * tek yazar servistir; ERP bu alani salt-okur gosterir).
  86.      * @ORM\Column(type="text", nullable=true)
  87.      * @Groups({
  88.      *      "project_order_task_job@core"
  89.      *   })
  90.      */
  91.     private $note;
  92.     public function getId(): ?int
  93.     {
  94.         return $this->id;
  95.     }
  96.     public function getOrderTask(): ?ProjectOrderTasks
  97.     {
  98.         return $this->order_task;
  99.     }
  100.     public function setOrderTask(?ProjectOrderTasks $order_task): self
  101.     {
  102.         $this->order_task = $order_task;
  103.         return $this;
  104.     }
  105.     public function getJobWeight(): ?float
  106.     {
  107.         return $this->job_weight;
  108.     }
  109.     public function setJobWeight(?float $job_weight): self
  110.     {
  111.         $this->job_weight = $job_weight;
  112.         return $this;
  113.     }
  114.     public function getJobIndex(): ?int
  115.     {
  116.         return $this->job_index;
  117.     }
  118.     public function setJobIndex(int $job_index): self
  119.     {
  120.         $this->job_index = $job_index;
  121.         return $this;
  122.     }
  123.     public function getStartAt(): ?\DateTimeImmutable
  124.     {
  125.         return $this->start_at;
  126.     }
  127.     public function setStartAt(?\DateTimeImmutable $start_at): self
  128.     {
  129.         $this->start_at = $start_at;
  130.         return $this;
  131.     }
  132.     public function getEndAt(): ?\DateTimeImmutable
  133.     {
  134.         return $this->end_at;
  135.     }
  136.     public function setEndAt(?\DateTimeImmutable $end_at): self
  137.     {
  138.         $this->end_at = $end_at;
  139.         return $this;
  140.     }
  141.     /**
  142.      * Tamamlama kilidi — İKİ otoriteden OKUNUR (read-through; order kendi tutmaz):
  143.      *  1) PLAN job'u kilitliyse (WorksPlan = lock otoritesi, mevcut davranış)
  144.      *  2) Task'ın TaskExecution kaydı `published` ise (K5, 2026-08-10 karar) — yayın
  145.      *     sonrası tek yazar servistir, ERP job'u artık kendi ekranından değiştiremez.
  146.      * Unlock yetkisi ilgili otoritededir (plan sahibi / servis).
  147.      *
  148.      * @Groups({
  149.      *       "project_order_task_job@core"
  150.      *    })
  151.      */
  152.     public function getLocked(): bool
  153.     {
  154.         if ($this->source_plan_job !== null && $this->source_plan_job->getLocked()) {
  155.             return true;
  156.         }
  157.         $task = $this->getOrderTask();
  158.         $execution = $task !== null ? $task->getTaskFulfillment() : null;
  159.         return $execution !== null && $execution->getStatus() === \App\Enum\TaskExecutionStatusEnum::PUBLISHED;
  160.     }
  161.     /**
  162.      * Tamamlama kilidi — SERVIS HELPER'ı (serialize EDİLMEZ). Job tamamlanmamış (end_at null)
  163.      * VE başlangıç günü gelmemişse (today < start_at) doldurulur; aksi halde null.
  164.      * Job tamamlama "live request" (job-completion-check endpoint → checkJobCompletion) bunu
  165.      * çağırır; eski serialize-edilen `completion_block` alanı kaldırıldı (FE artık endpoint kullanıyor).
  166.      *
  167.      * @return array|null
  168.      */
  169.     public function getCompletionBlock(): ?array
  170.     {
  171.         if ($this->end_at !== null) {
  172.             return null;
  173.         }
  174.         // Plan-bağlı job: start OTORİTESİ plan (order kopyası stale olabilir — plan ayrı yerde
  175.         // değişip order reload edilmemişse). Canlı check stale start yüzünden haksız blok vermesin.
  176.         $start = $this->source_plan_job !== null ? $this->source_plan_job->getStartAt() : $this->start_at;
  177.         if ($start === null) {
  178.             return null;
  179.         }
  180.         // Tarih-string: bugün == başlangıç günü ise tamamlanabilir (saat bileşeni şişirmesin).
  181.         $todayStr = (new \DateTimeImmutable('today'))->format('Y-m-d');
  182.         if ($start->format('Y-m-d') > $todayStr) {
  183.             return ['reason' => 'not_started', 'start_at' => $start->format('Y-m-d')];
  184.         }
  185.         return null;
  186.     }
  187.     public function getRating(): ?float
  188.     {
  189.         return $this->rating;
  190.     }
  191.     public function setRating(?float $rating): self
  192.     {
  193.         $this->rating = $rating;
  194.         return $this;
  195.     }
  196.     public function getRealDays(): ?int
  197.     {
  198.         return $this->real_days;
  199.     }
  200.     public function setRealDays(?int $real_days): self
  201.     {
  202.         $this->real_days = $real_days;
  203.         return $this;
  204.     }
  205.     public function getJobDescription(): ?string
  206.     {
  207.         return $this->job_description;
  208.     }
  209.     public function setJobDescription(?string $job_description): self
  210.     {
  211.         $this->job_description = $job_description;
  212.         return $this;
  213.     }
  214.     public function getDurationDays(): ?float
  215.     {
  216.         return $this->duration_days;
  217.     }
  218.     public function setDurationDays(?float $duration_days): self
  219.     {
  220.         $this->duration_days = $duration_days;
  221.         return $this;
  222.     }
  223.     public function getNote(): ?string
  224.     {
  225.         return $this->note;
  226.     }
  227.     public function setNote(?string $note): self
  228.     {
  229.         $this->note = $note;
  230.         return $this;
  231.     }
  232.     /**
  233.      * Materialization mapping — bu Order TaskJob hangi WorksPlanJob'dan üretildi.
  234.      * end_at değiştiğinde OrderEndAtBackSyncListener bu kolondan Plan job'una ulaşıp
  235.      * is_end_at'i set eder. Plan job silinirse NULL'a düşer (Order satırı kalır).
  236.      *
  237.      * @ORM\ManyToOne(targetEntity=WorksPlanJob::class)
  238.      * @ORM\JoinColumn(name="source_plan_job_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
  239.      *
  240.      * NOT: Serialize EDİLMEZ (group YOK) — order FE'sine sızarsa save'de generic
  241.      * hydrator setSourcePlanJob(array) ile patlar. Yalnızca BE Materializer/back-sync kullanır.
  242.      */
  243.     private $source_plan_job;
  244.     public function getSourcePlanJob(): ?WorksPlanJob
  245.     {
  246.         return $this->source_plan_job;
  247.     }
  248.     public function setSourcePlanJob(?WorksPlanJob $source_plan_job): self
  249.     {
  250.         $this->source_plan_job = $source_plan_job;
  251.         return $this;
  252.     }
  253. }