<?php
namespace App\Entity;
use App\Repository\MaterialRequestRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* MaterialRequest — in-house (execution_scope=internal) production task'inda, task'i
* ustlenen responsible person'in (TaskExecution.branch_contact_person) actigi malzeme
* siparis talebi. Talebe birden fazla PDF (MaterialRequestDocument) eklenir; bir
* TaskExecution icin birden fazla talep acilabilir (bu yuzden ManyToOne, OneToOne DEGIL).
*
* Sistem PDF'i PARSE ETMEZ. Durum PDF'lerden TURER (recomputeStatusFromDocuments,
* upsertV2 deseni: BE hesaplar, PERSIST eder — bkz. TaskExecutionService::recomputeDerivedFieldsFromJobs).
*
* @ORM\Entity(repositoryClass=MaterialRequestRepository::class)
* @ORM\HasLifecycleCallbacks
*/
class MaterialRequest
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({
* "material_request@ref",
* "material_request@base",
* "material_request@core"
* })
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=ProjectOrderTaskFulfillment::class)
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Groups({
* "material_request@task_execution"
* })
*/
private $task_execution;
/**
* Talebi acan kisi — in-house execution'in responsible person'i
* (TaskExecution.branch_contact_person ile ayni WorkerActivities).
* @ORM\ManyToOne(targetEntity=WorkerActivities::class)
* @ORM\JoinColumn(nullable=false)
* @Groups({
* "material_request@requester"
* })
*/
private $requester;
/**
* Default'un TEK kaynagi burasi (property default) — Doctrine Type sadece gecerli
* degerleri dogrular, varsayilan atamaz.
* @ORM\Column(type="material_request_status", nullable=false, options={"default": "draft"})
* @Groups({
* "material_request@base",
* "material_request@core"
* })
*/
private $status = 'draft';
/**
* Kararı veren Expenses sorumlusu — ilk/son karar aninda set edilir.
* @ORM\ManyToOne(targetEntity=WorkerActivities::class)
* @ORM\JoinColumn(nullable=true)
* @Groups({
* "material_request@reviewer"
* })
*/
private $reviewer;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "material_request@core"
* })
*/
private $submitted_at;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "material_request@core"
* })
*/
private $reviewed_at;
/**
* Talep sahibine EN SON ne zaman karar bildirimi e-postasi gonderildi.
*
* Neden tutuluyor: karar maili KAYIT BASINA tek ozet gidiyor (kullanici karari
* 2026-08-20). Ayni talebe sonradan tekrar karar verilirse ERP "bu talep icin
* daha once mail gitmisti, tekrar gondermek ister misin?" diye SORAR. O soruyu
* sorabilmek icin "gonderildi mi" bilgisinin kalici olmasi gerekiyor — aksi
* halde her kayitta sessizce mail giderdi ve kullanicinin dedigi gibi
* "sinir bozucu" olurdu.
*
* NULL = bu talep icin hic karar bildirimi gonderilmedi.
*
* 🪤 `reviewed_at` ILE KARISTIRMA: o KARARIN ne zaman verildigini soyler,
* bu ise BILDIRIMIN ne zaman gonderildigini. Ikisi ayri olaydir; karar
* verilip mail gonderilmemis olabilir (kullanici "gonderme" der).
*
* @ORM\Column(type="datetime_immutable", nullable=true)
* @Groups({
* "material_request@core"
* })
*/
private $last_decision_mail_at;
/**
* @ORM\Column(type="datetime_immutable", nullable=false)
* @Groups({
* "material_request@core"
* })
*/
private $created_at;
/**
* @ORM\OneToMany(targetEntity=MaterialRequestDocument::class, mappedBy="material_request", cascade={"persist"}, orphanRemoval=true)
* @Groups({
* "material_request@documents"
* })
*/
private $documents;
public function __construct()
{
$this->documents = new ArrayCollection();
}
/**
* @ORM\PrePersist
*/
public function onPrePersist(): void
{
if ($this->created_at === null) {
$this->created_at = new \DateTimeImmutable();
}
}
public function getId(): ?int
{
return $this->id;
}
public function getTaskExecution(): ?ProjectOrderTaskFulfillment
{
return $this->task_execution;
}
public function setTaskExecution(?ProjectOrderTaskFulfillment $task_execution): self
{
$this->task_execution = $task_execution;
return $this;
}
public function getRequester(): ?WorkerActivities
{
return $this->requester;
}
public function setRequester(?WorkerActivities $requester): self
{
$this->requester = $requester;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getReviewer(): ?WorkerActivities
{
return $this->reviewer;
}
public function setReviewer(?WorkerActivities $reviewer): self
{
$this->reviewer = $reviewer;
return $this;
}
public function getSubmittedAt(): ?\DateTimeImmutable
{
return $this->submitted_at;
}
public function getLastDecisionMailAt(): ?\DateTimeImmutable
{
return $this->last_decision_mail_at;
}
public function setLastDecisionMailAt(?\DateTimeImmutable $last_decision_mail_at): self
{
$this->last_decision_mail_at = $last_decision_mail_at;
return $this;
}
public function setSubmittedAt(?\DateTimeImmutable $submitted_at): self
{
$this->submitted_at = $submitted_at;
return $this;
}
public function getReviewedAt(): ?\DateTimeImmutable
{
return $this->reviewed_at;
}
public function setReviewedAt(?\DateTimeImmutable $reviewed_at): self
{
$this->reviewed_at = $reviewed_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;
}
/**
* @return Collection<int, MaterialRequestDocument>
*/
public function getDocuments(): Collection
{
return $this->documents;
}
public function addDocument(MaterialRequestDocument $document): self
{
if (!$this->documents->contains($document)) {
$this->documents[] = $document;
$document->setMaterialRequest($this);
}
return $this;
}
public function removeDocument(MaterialRequestDocument $document): self
{
if ($this->documents->removeElement($document)) {
if ($document->getMaterialRequest() === $this) {
$document->setMaterialRequest(null);
}
}
return $this;
}
}