src/Entity/ProjectOrderTaskFulfillment.php line 15

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\ProjectOrderTaskFulfillmentRepository;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Collection;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Symfony\Component\Serializer\Annotation\Groups;
  8. use Symfony\Component\Serializer\Annotation\SerializedName;
  9. /**
  10.  * @ORM\Entity(repositoryClass=ProjectOrderTaskFulfillmentRepository::class)
  11.  */
  12. class ProjectOrderTaskFulfillment
  13. {
  14.     /**
  15.      * @ORM\Id
  16.      * @ORM\GeneratedValue
  17.      * @ORM\Column(type="integer")
  18.      * @Groups({
  19.      *     "project_order_task_fulfillment@ref",
  20.      *     "project_order_task_fulfillment@base",
  21.      *     "project_order_task_fulfillment@core"
  22.      * })
  23.      */
  24.     private $id;
  25.     /**
  26.      * @ORM\ManyToOne(targetEntity=Vendor::class, inversedBy="project_order_task_fulfillments")
  27.      * @ORM\JoinColumn(nullable=true, options={"comment": "Use this data if scope:External & work-natue: support&production"})
  28.      * @Groups({
  29.      *      "project_order_task_fulfillment@vendor"
  30.      *  })
  31.      */
  32.     private $vendor;
  33.     /**
  34.      * @ORM\ManyToOne(targetEntity=VendorContactPersons::class, inversedBy="project_order_task_fulfillments")
  35.      * @ORM\JoinColumn(nullable=true, options={"comment": "Use this data if scope:External & work-natue: support&production"})
  36.      * @Groups({
  37.      *     "project_order_task_fulfillment@contact_person"
  38.      * })
  39.      */
  40.     private $vendor_contact_person;
  41.     /**
  42.      * @ORM\Column(type="text", nullable=true)
  43.      * @Groups({
  44.      *      "project_order_task_fulfillment@core"
  45.      *  })
  46.      */
  47.     private $work_content;
  48.     /**
  49.      * 2026-08-10 karar: yeni TaskExecution akisi reason sormuyor (wizard'da yok) ->
  50.      * nullable=true yapildi. Eski Fulfillment dialog'unun `reason` zorunlu tuttugu
  51.      * senaryo hala calisir (alan opsiyonel oldu, zorunlulugu FE tarafinda kaldi).
  52.      * @ORM\ManyToOne(targetEntity=TaskFulfillmentReasons::class, inversedBy="project_order_task_fulfillments")
  53.      * @ORM\JoinColumn(nullable=true)
  54.      * @Groups({
  55.      *     "project_order_task_fulfillment@reason"
  56.      * })
  57.      */
  58.     private $reason;
  59.     // "project_order_task_fulfillment@task"
  60.     /**
  61.      * @ORM\OneToOne(targetEntity=ProjectOrderTasks::class, inversedBy="task_fulfillment")
  62.      * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
  63.      * @Groups({
  64.      *      "project_order_task_fulfillment@task"
  65.      *  })
  66.      */
  67.     private $task;
  68.     /**
  69.      * @ORM\Column(type="boolean", nullable=true)
  70.      * @Groups({
  71.      *     "project_order_task_fulfillment@core"
  72.      * })
  73.      */
  74.     private $is_linked;
  75.     /**
  76.      * @ORM\Column(type="date_immutable", nullable=true)
  77.      * @Groups({
  78.      *       "project_order_task_fulfillment@core"
  79.      *   })
  80.      */
  81.     private $planned_start_at;
  82.     /**
  83.      * @ORM\Column(type="date_immutable", nullable=true)
  84.      * @Groups({
  85.      *       "project_order_task_fulfillment@core"
  86.      *   })
  87.      */
  88.     private $planned_end_at;
  89.     /**
  90.      * @ORM\Column(type="date_immutable", nullable=true)
  91.      * @Groups({
  92.      *       "project_order_task_fulfillment@core"
  93.      *   })
  94.      */
  95.     private $actual_end_at;
  96.     /**
  97.      * @ORM\Column(type="date_immutable", nullable=true)
  98.      * @Groups({
  99.      *       "project_order_task_fulfillment@core"
  100.      *   })
  101.      */
  102.     private $delivery_at;
  103.     /**
  104.      * @ORM\Column(type="text", nullable=true)
  105.      * @Groups({
  106.      *       "project_order_task_fulfillment@core"
  107.      *   })
  108.      */
  109.     private $delivery_note;
  110.     /**
  111.      * @ORM\Column(type="float", nullable=true)
  112.      * @Groups({
  113.      *       "project_order_task_fulfillment@core"
  114.      *   })
  115.      */
  116.     private $rating;
  117.     /**
  118.      * @ORM\Column(type="float", nullable=true)
  119.      * @Groups({
  120.      *        "project_order_task_fulfillment@core"
  121.      *    })
  122.      */
  123.     private $cost;
  124.     /**
  125.      * @ORM\Column(type="string", length=64, nullable=true)
  126.      * @Groups({
  127.      *         "project_order_task_fulfillment@core"
  128.      *     })
  129.      */
  130.     private $contract_reference_nr;
  131.     /**
  132.      * @ORM\ManyToOne(targetEntity=ContractTypes::class, inversedBy="project_order_task_fulfillments")
  133.      * @Groups({
  134.      *          "project_order_task_fulfillment@contract_type"
  135.      *      })
  136.      */
  137.     private $contract_type;
  138.     /**
  139.      * @ORM\OneToMany(targetEntity=ProjectOrderTaskFulfillmentWorkDocs::class, mappedBy="project_order_task_fulfillment", cascade={"persist"}, orphanRemoval=true)
  140.      * @Groups({
  141.      *      "project_order_task_fulfillment@work_documents"
  142.      *  })
  143.      */
  144.     private $work_documents;
  145.     /**
  146.      * Gerekçeli tarih revizyon zinciri (kullanıcı kararı 2026-08-11). GÜNCEL tarih = EN SON revizyon;
  147.      * committed_* buradan türetilir. İlk satır = kabul (reason null), sonrakiler gerekçeli revizyon.
  148.      *
  149.      * @ORM\OneToMany(targetEntity=ProjectOrderTaskFulfillmentDateRevision::class, mappedBy="project_order_task_fulfillment", cascade={"persist"}, orphanRemoval=true)
  150.      * @ORM\OrderBy({"created_at" = "ASC", "id" = "ASC"})
  151.      * @Groups({
  152.      *      "project_order_task_fulfillment@core"
  153.      *  })
  154.      */
  155.     private $date_revisions;
  156.     /**
  157.      * @ORM\Column(type="task_execution_scope", nullable=true)
  158.      * @Groups({
  159.      *       "project_order_task_fulfillment@core",
  160.      *       "project_order_task_fulfillment@progress"
  161.      * })
  162.      */
  163.     private $execution_scope;
  164.     /**
  165.      * @ORM\Column(type="task_execution_work_nature", nullable=true)
  166.      * @Groups({
  167.      *       "project_order_task_fulfillment@core"
  168.      * })
  169.      */
  170.     private $execution_work_nature;
  171.     /**
  172.      * @ORM\ManyToOne(targetEntity=Branches::class, inversedBy="project_order_task_fulfillments")
  173.      * @ORM\JoinColumn(options={"comment": "Use this data if fulfillment is internal&production"})
  174.      * @Groups({
  175.      *        "project_order_task_fulfillment@branch"
  176.      *  })
  177.      */
  178.     private $branch;
  179.     /**
  180.      * @ORM\ManyToOne(targetEntity=WorkerActivities::class, inversedBy="project_order_task_fulfillments")
  181.      * @ORM\JoinColumn(options={"comment": "Use this data if fulfillment is internal&production"})
  182.      * @Groups({
  183.      *         "project_order_task_fulfillment@branch_contact_person"
  184.      *   })
  185.      */
  186.     private $branch_contact_person;
  187.     /**
  188.      * R3 — task execution'i FIILEN publish eden aktivite (lead, vekil VEYA admin olabilir).
  189.      * publish() aninda set edilir; "bunu kim yayinladi" attribution'i (ozellikle actor != lead iken).
  190.      * @ORM\ManyToOne(targetEntity=WorkerActivities::class)
  191.      * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
  192.      * @Groups({
  193.      *         "project_order_task_fulfillment@core",
  194.      *         "project_order_task_fulfillment@published_by"
  195.      *   })
  196.      */
  197.     private $published_by;
  198.     /**
  199.      * TaskExecution akisi durumu: draft (K4 — task icin acilan taslak, henuz servise
  200.      * verilmedi) | published (K5 — servise devredildi, bundan sonra tek yazar servistir).
  201.      * Default'un TEK kaynagi burasi (property default) — Doctrine Type sadece gecerli
  202.      * degerleri dogrular, varsayilan atamaz.
  203.      * @ORM\Column(type="task_execution_status", nullable=false, options={"default": "draft"})
  204.      * @Groups({
  205.      *     "project_order_task_fulfillment@core",
  206.      *     "project_order_task_fulfillment@progress"
  207.      * })
  208.      */
  209.     private $status = 'draft';
  210.     /**
  211.      * Servise ne zaman devredildi (publish anindaki timestamp).
  212.      * @ORM\Column(type="datetime_immutable", nullable=true)
  213.      * @Groups({
  214.      *     "project_order_task_fulfillment@core"
  215.      * })
  216.      */
  217.     private $published_at;
  218.     /**
  219.      * K8 — icra eden kisi (vendor_contact_person / branch_contact_person) isi KABUL ettiginde
  220.      * (servis tarafindaki "Is kabul edildi" butonu) doldurulan timestamp. Kabul = published +
  221.      * accepted_at dolu. Yeni status ENUM degeri EKLENMEDI (karar 11: zengin status reddedildi);
  222.      * accepted_at aynasi published_at gibi tutulur. Yalniz servis (ag-ici accept ucu) yazar
  223.      * (K5 — yayin sonrasi tek yazar servis). Silme kilidi bu alana bagli: dolu ise task silinemez.
  224.      * @ORM\Column(type="datetime_immutable", nullable=true)
  225.      * @Groups({
  226.      *     "project_order_task_fulfillment@core",
  227.      *     "project_order_task_fulfillment@progress"
  228.      * })
  229.      */
  230.     private $accepted_at;
  231.     /**
  232.      * K8-accept — icra eden kisi isi REDDETTIGINDE (servis "Reddet" butonu) dolan timestamp.
  233.      * Alt-durum: published + accepted_at NULL + declined_at NULL = Pending; accepted_at dolu =
  234.      * Accepted; declined_at dolu = Declined. Yalniz servis yazar (K5). Reddedilen is geri
  235.      * sahibine doner → SILINEBILIR (yalniz accepted silme kilidi tetikler, declined DEGIL).
  236.      * @ORM\Column(type="datetime_immutable", nullable=true)
  237.      * @Groups({
  238.      *     "project_order_task_fulfillment@core",
  239.      *     "project_order_task_fulfillment@progress"
  240.      * })
  241.      */
  242.     private $declined_at;
  243.     /**
  244.      * PEER BATCH (2026-08-16) — RED gerekçe KATEGORİSİ. `reason_category` ile aynı deseni
  245.      * kullanır (App\Enum\TaskExecutionReasonCategoryEnum — supply/personnel/weather/
  246.      * scope_change/other, tarih revizyonuyla AYNI enum, yeni bir tane açılmadı). Opsiyonel —
  247.      * decline BE'de zorunlu tutulmuyor (K8-decline zaten idempotent bir aksiyon). `@core`'da
  248.      * → ERP owner reddin sebebini görebilsin.
  249.      * @ORM\Column(type="task_execution_reason_category", nullable=true)
  250.      * @Groups({
  251.      *     "project_order_task_fulfillment@core"
  252.      * })
  253.      */
  254.     private $decline_reason_category;
  255.     /**
  256.      * PEER BATCH (2026-08-16) — RED gerekçesi serbest metin. `decline_reason_category`'nin
  257.      * YANINDA (kategori + serbest metin ikilisi, tarih revizyonuyla aynı desen). Yalnız
  258.      * icra eden (servis, internal decline ucu) yazar.
  259.      * @ORM\Column(type="string", length=1000, nullable=true)
  260.      * @Groups({
  261.      *     "project_order_task_fulfillment@core"
  262.      * })
  263.      */
  264.     private $decline_reason;
  265.     /**
  266.      * Task-bazlı owner⟷executor mesajlaşma zinciri (karar 59, Chat-K1/Chat-K2). created_at ile
  267.      * sıralı. ⚠️ Bilerek Groups anotasyonu YOK — mesaj İÇERİĞİ bu payload'a (serializeFull/
  268.      * serializeFullWithJobs/serializeFullPreview) ASLA karışmaz; ayrı uçlardan (message/list,
  269.      * internal/message/list, internal/messages/recent) gelir (Chat-K1).
  270.      * @ORM\OneToMany(targetEntity=ProjectOrderTaskFulfillmentMessage::class, mappedBy="execution", cascade={"persist"}, orphanRemoval=true)
  271.      * @ORM\OrderBy({"created_at" = "ASC", "id" = "ASC"})
  272.      */
  273.     private $messages;
  274.     /**
  275.      * Chat-K2 (karar 59b) — owner tarafı mesajları EN SON ne zaman okudu. Geriye dönük
  276.      * üretilemez, bu yüzden BAŞTAN eklendi. 🪤 Bilerek `@core`'a KONMADI — executor bu alanı
  277.      * (owner'ın okuma izini) GÖRMEMELİ. Ayrı grup (`@read_state`); yalnız message/list +
  278.      * internal/message/list + internal/messages/recent servis-katmanı hesaplarında okunur.
  279.      * @ORM\Column(type="datetime_immutable", nullable=true)
  280.      * @Groups({
  281.      *     "project_order_task_fulfillment@read_state"
  282.      * })
  283.      */
  284.     private $owner_last_read_at;
  285.     /**
  286.      * Chat-K2 (karar 59b) — executor tarafı mesajları EN SON ne zaman okudu. Simetrik neden:
  287.      * owner bu alanı (executor'ın okuma izini) GÖRMEMELİ. Bkz. $owner_last_read_at.
  288.      * @ORM\Column(type="datetime_immutable", nullable=true)
  289.      * @Groups({
  290.      *     "project_order_task_fulfillment@read_state"
  291.      * })
  292.      */
  293.     private $executor_last_read_at;
  294.     public function __construct()
  295.     {
  296.         $this->work_documents = new ArrayCollection();
  297.         $this->date_revisions = new ArrayCollection();
  298.         $this->messages = new ArrayCollection();
  299.     }
  300.     public function getId(): ?int
  301.     {
  302.         return $this->id;
  303.     }
  304.     public function getVendor(): ?Vendor
  305.     {
  306.         return $this->vendor;
  307.     }
  308.     public function setVendor(?Vendor $vendor): self
  309.     {
  310.         $this->vendor = $vendor;
  311.         return $this;
  312.     }
  313.     public function getVendorContactPerson(): ?VendorContactPersons
  314.     {
  315.         return $this->vendor_contact_person;
  316.     }
  317.     public function setVendorContactPerson(?VendorContactPersons $vendor_contact_person): self
  318.     {
  319.         $this->vendor_contact_person = $vendor_contact_person;
  320.         return $this;
  321.     }
  322.     public function getWorkContent(): ?string
  323.     {
  324.         return $this->work_content;
  325.     }
  326.     public function setWorkContent(?string $work_content): self
  327.     {
  328.         $this->work_content = $work_content;
  329.         return $this;
  330.     }
  331.     public function getReason(): ?TaskFulfillmentReasons
  332.     {
  333.         return $this->reason;
  334.     }
  335.     public function setReason(?TaskFulfillmentReasons $reason): self
  336.     {
  337.         $this->reason = $reason;
  338.         return $this;
  339.     }
  340.     public function getTask(): ?ProjectOrderTasks
  341.     {
  342.         return $this->task;
  343.     }
  344.     public function setTask(ProjectOrderTasks $task): self
  345.     {
  346.         $this->task = $task;
  347.         return $this;
  348.     }
  349.     /**
  350.      * Order listesi çipi için execution ilerlemesi (% 0-100). Task'ın job'larından türer:
  351.      * Σ(biten job_weight) / Σ(job_weight) × 100 — biten = start_at VE end_at dolu (OrderCalculator
  352.      * ile aynı "done" tanımı). SANAL: DB kolonu DEĞİL, serialize anında hesaplanır. Yalnız
  353.      * `@progress` grubu (order listesi) ile döner → `@core` payload'ı şişmez, per-execution çip verisi.
  354.      *
  355.      * @Groups({
  356.      *     "project_order_task_fulfillment@progress"
  357.      * })
  358.      * @SerializedName("execution_progress")
  359.      */
  360.     public function getExecutionProgress(): ?float
  361.     {
  362.         $task = $this->task;
  363.         if ($task === null) {
  364.             return null;
  365.         }
  366.         $totalWeight = 0.0;
  367.         $doneWeight = 0.0;
  368.         foreach ($task->getTaskJobs() as $job) {
  369.             $weight = (float) $job->getJobWeight();
  370.             $totalWeight += $weight;
  371.             if ($job->getStartAt() !== null && $job->getEndAt() !== null) {
  372.                 $doneWeight += $weight;
  373.             }
  374.         }
  375.         if ($totalWeight <= 0.0) {
  376.             return 0.0;
  377.         }
  378.         return round(($doneWeight / $totalWeight) * 100, 2);
  379.     }
  380.     public function isIsLinked(): ?bool
  381.     {
  382.         return $this->is_linked;
  383.     }
  384.     public function setIsLinked(?bool $is_linked): self
  385.     {
  386.         $this->is_linked = $is_linked;
  387.         return $this;
  388.     }
  389.     public function getPlannedStartAt(): ?\DateTimeImmutable
  390.     {
  391.         return $this->planned_start_at;
  392.     }
  393.     public function setPlannedStartAt(?\DateTimeImmutable $planned_start_at): self
  394.     {
  395.         $this->planned_start_at = $planned_start_at;
  396.         return $this;
  397.     }
  398.     public function getPlannedEndAt(): ?\DateTimeImmutable
  399.     {
  400.         return $this->planned_end_at;
  401.     }
  402.     public function setPlannedEndAt(?\DateTimeImmutable $planned_end_at): self
  403.     {
  404.         $this->planned_end_at = $planned_end_at;
  405.         return $this;
  406.     }
  407.     public function getActualEndAt(): ?\DateTimeImmutable
  408.     {
  409.         return $this->actual_end_at;
  410.     }
  411.     public function setActualEndAt(?\DateTimeImmutable $actual_end_at): self
  412.     {
  413.         $this->actual_end_at = $actual_end_at;
  414.         return $this;
  415.     }
  416.     public function getDeliveryAt(): ?\DateTimeImmutable
  417.     {
  418.         return $this->delivery_at;
  419.     }
  420.     public function setDeliveryAt(?\DateTimeImmutable $delivery_at): self
  421.     {
  422.         $this->delivery_at = $delivery_at;
  423.         return $this;
  424.     }
  425.     public function getDeliveryNote(): ?string
  426.     {
  427.         return $this->delivery_note;
  428.     }
  429.     public function setDeliveryNote(?string $delivery_note): self
  430.     {
  431.         $this->delivery_note = $delivery_note;
  432.         return $this;
  433.     }
  434.     public function getRating(): ?float
  435.     {
  436.         return $this->rating;
  437.     }
  438.     public function setRating(?float $rating): self
  439.     {
  440.         $this->rating = $rating;
  441.         return $this;
  442.     }
  443.     public function getCost(): ?float
  444.     {
  445.         return $this->cost;
  446.     }
  447.     public function setCost(?float $cost): self
  448.     {
  449.         $this->cost = $cost;
  450.         return $this;
  451.     }
  452.     public function getContractReferenceNr(): ?string
  453.     {
  454.         return $this->contract_reference_nr;
  455.     }
  456.     public function setContractReferenceNr(?string $contract_reference_nr): self
  457.     {
  458.         $this->contract_reference_nr = $contract_reference_nr;
  459.         return $this;
  460.     }
  461.     public function getContractType(): ?ContractTypes
  462.     {
  463.         return $this->contract_type;
  464.     }
  465.     public function setContractType(?ContractTypes $contract_type): self
  466.     {
  467.         $this->contract_type = $contract_type;
  468.         return $this;
  469.     }
  470.     /**
  471.      * @return Collection<int, ProjectOrderTaskFulfillmentWorkDocs>
  472.      */
  473.     public function getWorkDocuments(): Collection
  474.     {
  475.         return $this->work_documents;
  476.     }
  477.     public function addProjectOrderTaskFulfillmentWorkDoc(ProjectOrderTaskFulfillmentWorkDocs $projectOrderTaskFulfillmentWorkDocs): self
  478.     {
  479.         if (!$this->work_documents->contains($projectOrderTaskFulfillmentWorkDocs)) {
  480.             $this->work_documents[] = $projectOrderTaskFulfillmentWorkDocs;
  481.             $projectOrderTaskFulfillmentWorkDocs->setProjectOrderTaskFulfillment($this);
  482.         }
  483.         return $this;
  484.     }
  485.     public function removeProjectOrderTaskFulfillmentWorkDoc(ProjectOrderTaskFulfillmentWorkDocs $projectOrderTaskFulfillmentWorkDocs): self
  486.     {
  487.         if ($this->work_documents->removeElement($projectOrderTaskFulfillmentWorkDocs)) {
  488.             // set the owning side to null (unless already changed)
  489.             if ($projectOrderTaskFulfillmentWorkDocs->getProjectOrderTaskFulfillment() === $this) {
  490.                 $projectOrderTaskFulfillmentWorkDocs->setProjectOrderTaskFulfillment(null);
  491.             }
  492.         }
  493.         return $this;
  494.     }
  495.     /**
  496.      * @return Collection<int, ProjectOrderTaskFulfillmentDateRevision>
  497.      */
  498.     public function getDateRevisions(): Collection
  499.     {
  500.         return $this->date_revisions;
  501.     }
  502.     public function addDateRevision(ProjectOrderTaskFulfillmentDateRevision $revision): self
  503.     {
  504.         if (!$this->date_revisions->contains($revision)) {
  505.             $this->date_revisions[] = $revision;
  506.             $revision->setProjectOrderTaskFulfillment($this);
  507.         }
  508.         return $this;
  509.     }
  510.     /** EN SON (created_at max) revizyon = güncel taahhüt. Zincir boşsa null. */
  511.     private function getLatestDateRevision(): ?ProjectOrderTaskFulfillmentDateRevision
  512.     {
  513.         $latest = null;
  514.         foreach ($this->date_revisions as $revision) {
  515.             if ($latest === null || $revision->getCreatedAt() >= $latest->getCreatedAt()) {
  516.                 $latest = $revision;
  517.             }
  518.         }
  519.         return $latest;
  520.     }
  521.     /**
  522.      * Taahhüt edilen başlangıç = son revizyonun start_at'i (yoksa null). SANAL — zincirden türer.
  523.      *
  524.      * @Groups({
  525.      *     "project_order_task_fulfillment@core"
  526.      * })
  527.      * @SerializedName("committed_start_at")
  528.      */
  529.     public function getCommittedStartAt(): ?\DateTimeImmutable
  530.     {
  531.         $latest = $this->getLatestDateRevision();
  532.         return $latest !== null ? $latest->getStartAt() : null;
  533.     }
  534.     /**
  535.      * Taahhüt edilen bitiş = son revizyonun end_at'i (yoksa null). SANAL — zincirden türer.
  536.      *
  537.      * @Groups({
  538.      *     "project_order_task_fulfillment@core"
  539.      * })
  540.      * @SerializedName("committed_end_at")
  541.      */
  542.     public function getCommittedEndAt(): ?\DateTimeImmutable
  543.     {
  544.         $latest = $this->getLatestDateRevision();
  545.         return $latest !== null ? $latest->getEndAt() : null;
  546.     }
  547.     public function getExecutionScope(): ?string
  548.     {
  549.         return $this->execution_scope;
  550.     }
  551.     public function setExecutionScope(?string $execution_scope): self
  552.     {
  553.         $this->execution_scope = $execution_scope;
  554.         return $this;
  555.     }
  556.     public function getExecutionWorkNature()
  557.     {
  558.         return $this->execution_work_nature;
  559.     }
  560.     public function setExecutionWorkNature($execution_work_nature): void
  561.     {
  562.         $this->execution_work_nature = $execution_work_nature;
  563.     }
  564.     public function getBranch(): ?Branches
  565.     {
  566.         return $this->branch;
  567.     }
  568.     public function setBranch(?Branches $branch): self
  569.     {
  570.         $this->branch = $branch;
  571.         return $this;
  572.     }
  573.     public function getBranchContactPerson(): ?WorkerActivities
  574.     {
  575.         return $this->branch_contact_person;
  576.     }
  577.     public function setBranchContactPerson(?WorkerActivities $branch_contact_person): self
  578.     {
  579.         $this->branch_contact_person = $branch_contact_person;
  580.         return $this;
  581.     }
  582.     public function getPublishedBy(): ?WorkerActivities
  583.     {
  584.         return $this->published_by;
  585.     }
  586.     public function setPublishedBy(?WorkerActivities $published_by): self
  587.     {
  588.         $this->published_by = $published_by;
  589.         return $this;
  590.     }
  591.     public function getStatus(): ?string
  592.     {
  593.         return $this->status;
  594.     }
  595.     public function setStatus(string $status): self
  596.     {
  597.         $this->status = $status;
  598.         return $this;
  599.     }
  600.     public function getPublishedAt(): ?\DateTimeImmutable
  601.     {
  602.         return $this->published_at;
  603.     }
  604.     public function setPublishedAt(?\DateTimeImmutable $published_at): self
  605.     {
  606.         $this->published_at = $published_at;
  607.         return $this;
  608.     }
  609.     public function getAcceptedAt(): ?\DateTimeImmutable
  610.     {
  611.         return $this->accepted_at;
  612.     }
  613.     public function setAcceptedAt(?\DateTimeImmutable $accepted_at): self
  614.     {
  615.         $this->accepted_at = $accepted_at;
  616.         return $this;
  617.     }
  618.     /** K8 — kabul edildi mi (published + accepted_at dolu). Silme kilidi ve FE rozeti bunu okur. */
  619.     public function isAccepted(): bool
  620.     {
  621.         return $this->accepted_at !== null;
  622.     }
  623.     public function getDeclinedAt(): ?\DateTimeImmutable
  624.     {
  625.         return $this->declined_at;
  626.     }
  627.     public function setDeclinedAt(?\DateTimeImmutable $declined_at): self
  628.     {
  629.         $this->declined_at = $declined_at;
  630.         return $this;
  631.     }
  632.     /** K8-accept — reddedildi mi (declined_at dolu). Reddedilen is silinebilir (accepted degil). */
  633.     public function isDeclined(): bool
  634.     {
  635.         return $this->declined_at !== null;
  636.     }
  637.     public function getDeclineReasonCategory(): ?string
  638.     {
  639.         return $this->decline_reason_category;
  640.     }
  641.     public function setDeclineReasonCategory(?string $decline_reason_category): self
  642.     {
  643.         $this->decline_reason_category = $decline_reason_category;
  644.         return $this;
  645.     }
  646.     public function getDeclineReason(): ?string
  647.     {
  648.         return $this->decline_reason;
  649.     }
  650.     public function setDeclineReason(?string $decline_reason): self
  651.     {
  652.         $this->decline_reason = $decline_reason;
  653.         return $this;
  654.     }
  655.     /**
  656.      * @return Collection<int, ProjectOrderTaskFulfillmentMessage>
  657.      */
  658.     public function getMessages(): Collection
  659.     {
  660.         return $this->messages;
  661.     }
  662.     public function addMessage(ProjectOrderTaskFulfillmentMessage $message): self
  663.     {
  664.         if (!$this->messages->contains($message)) {
  665.             $this->messages[] = $message;
  666.             $message->setExecution($this);
  667.         }
  668.         return $this;
  669.     }
  670.     public function getOwnerLastReadAt(): ?\DateTimeImmutable
  671.     {
  672.         return $this->owner_last_read_at;
  673.     }
  674.     public function setOwnerLastReadAt(?\DateTimeImmutable $owner_last_read_at): self
  675.     {
  676.         $this->owner_last_read_at = $owner_last_read_at;
  677.         return $this;
  678.     }
  679.     public function getExecutorLastReadAt(): ?\DateTimeImmutable
  680.     {
  681.         return $this->executor_last_read_at;
  682.     }
  683.     public function setExecutorLastReadAt(?\DateTimeImmutable $executor_last_read_at): self
  684.     {
  685.         $this->executor_last_read_at = $executor_last_read_at;
  686.         return $this;
  687.     }
  688. }