<?php
namespace App\Entity;
use App\Repository\TaskFulfillmentStageRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* Uretim asamasi (Produktionsstatus) — TODO #109.
*
* Bir task'in uretim hattindaki yerini anlatan siralı liste (Auftragseingang →
* ... → Montagebereit). Asamayi SERVIS tarafi (icraci) secer, ERP salt-okur —
* modulun K5 kuralinin devami.
*
* NEDEN ENUM DEGIL TABLO (kullanici karari 2026-08-19): asama bir OZELLIK
* tasiyor (`is_start_stage` / `is_completion_stage`). ENUM degeri ozellik
* tasiyamaz. Ayrica liste zamanla degisecek — yeni asama eklenebilir, biri
* emekli edilebilir; bunun icin kod degisikligi/migration gerekmemeli.
*
* ETIKET BURADA TUTULUR, CEVIRI KATALOGUNDA DEGIL — ve bu bir eksiklik degil,
* kullanicinin karari (2026-08-19): asamalari sisteme koyan kisi KENDI dilinde
* yazar (Alman firma Almanca, Turk firma Turkce) ve o kurulumu kim acarsa acsin
* ayni metni gorur. Cok dilli karsilik ARANMIYOR. Teknik olarak da zorunlu:
* katalog derleme zamanina bagli, bu liste calisma zamanina — yarin eklenen bir
* asamanin katalogda karsiligi olamaz.
*
* 🪤 SILME YASAK — EMEKLILIK VAR (kullanici karari 2026-08-19). Bir asama bir
* task'a bagliysa SILINMEZ; yalnizca `active = false` yapilir. Boylece listede
* gorunmez ama gecmisteki task'lar hala ona baglidir ve etiketleri okunur.
*
* Bu kural yorumda BIRAKILMADI: `ProjectOrderTasks::$fulfillment_stage` ve
* gunluk kayitlari bu tabloya FK ile baglanir ve `onDelete` VERILMEZ —
* Doctrine varsayilani RESTRICT oldugu icin bagli bir satiri DB'nin kendisi
* sildirmez. Kurali kodu okumayan da ihlal edemez.
*
* Onceki tasarimda task kodu STRING olarak tutuyordu (gerekce: "asama silinirse
* gecmis bozulmasin"). Silme iptal edilince o gerekce dustu, geriye yalnizca
* kod ile etiketi senkron tutma zorunlulugu — yani tutarsizlik riski — kaldi.
*
* @ORM\Entity(repositoryClass=TaskFulfillmentStageRepository::class)
* @ORM\Table(name="task_fulfillment_stages")
*/
class TaskFulfillmentStage
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({
* "task_fulfillment_stage@ref",
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $id;
/**
* Dogal anahtar — task'a KOPYALANAN deger budur. Etiket degisse de anlam
* kaymasin diye sabit; ikinci kez ayni kod acilmasin diye UNIQUE.
* @ORM\Column(type="string", length=64, unique=true)
* @Groups({
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $code;
/**
* Ekranda gorunen ad (ör. "Montagebereit").
* @ORM\Column(type="string", length=255)
* @Groups({
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $label;
/**
* Listedeki sira. Araya yeni asama girebilsin diye 10'ar artan degerlerle
* seed edilir (10, 20, 30 …) — aradaki bosluk yeniden numaralandirmayi
* gereksiz kilar.
* @ORM\Column(type="integer")
* @Groups({
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $sort_index;
/**
* Is BASLADIGINDA (execution published) kullanilacak asama.
* 🪤 EN FAZLA BIR satirda true — guard servis tarafinda (MySQL'de kosullu
* unique index yok).
* @ORM\Column(type="boolean", options={"default": false})
* @Groups({
* "task_fulfillment_stage@core"
* })
*/
private $is_start_stage = false;
/**
* Task %100'e ulastiginda kullanilacak asama. Bayrakli satir yoksa ekranda
* genel "Completed" gosterilir.
* 🪤 EN FAZLA BIR satirda true (yukaridaki ile ayni guard).
* @ORM\Column(type="boolean", options={"default": false})
* @Groups({
* "task_fulfillment_stage@core"
* })
*/
private $is_completion_stage = false;
/**
* Rozet ARKA PLAN rengi — `#RRGGBB` (kullanici karari 2026-08-19).
*
* Her asamanin rengini YONETICI belirler ve o renk her yerde ayni kalir:
* pano, yeni gelenler, listeler, ERP kolonu, ERP ozeti. Renk kodda degil
* VERIDE oldugu icin yeni bir asama eklendiginde kod degisikligi gerekmez.
*
* 🪤 METIN RENGI AYRI KOLON DEGIL, HESAPLANIR. Iki kolon (bg + text)
* koysaydik yonetici koyu zemine koyu yazi secebilir ve rozet okunmaz
* hale gelirdi — kimse de fark etmezdi. Tek renk aliniyor, yazi rengi
* zeminin parlakligindan turetiliyor (bkz. FE `okunakliMetinRengi`).
* Boylece "okunmaz rozet" YAPISAL olarak imkansiz.
*
* NULL = tema varsayilani kullanilir; renk zorunlu degil.
*
* @ORM\Column(type="string", length=9, nullable=true)
* @Groups({
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $bg_color;
/**
* Bu asama HANGI NITELIKTEKI ise ait — gruplama icin (kullanici karari
* 2026-08-19).
*
* NULL = HER task icin gecerli (ortak asamalar).
* 'production' / 'service' = yalniz o nitelikteki isler icin anlamli.
*
* NEDEN AYRI LISTE DEGIL: kullanici tek liste istedi, ayrimi GRUPLAMA ile
* yapiyoruz. Boylece "Warten auf Verzinkerei" bir servis isinde ayri bir
* baslik altinda durur, ama liste yonetimi tek yerde kalir.
*
* 🪤 SUZME DEGIL GRUPLAMA: yanlis nitelikteki asamayi SECILEMEZ yapmiyoruz.
* Gercek hayatta servis isi de malzeme bekleyebiliyor; sert filtre koymak
* kullaniciyi cikmaza sokardi. Ekran gruplar, karari insan verir.
*
* 🪤 Tip `task_execution_work_nature` — task'in kendi nitelik kolonuyla AYNI
* enum. Ikinci bir "nitelik" listesi UYDURULMADI; yoksa iki liste zamanla
* ayrisirdi ('support' degeri yalniz burada olmaz).
*
* @ORM\Column(type="task_execution_work_nature", nullable=true)
* @Groups({
* "task_fulfillment_stage@base",
* "task_fulfillment_stage@core"
* })
*/
private $work_nature;
/**
* Emeklilik anahtari. SILMEK YERINE bunu false yap: satir durdugu icin eski
* task'larin kodu hala okunabilir bir etikete cevrilebilir, ama listede
* secilemez.
* @ORM\Column(type="boolean", options={"default": true})
* @Groups({
* "task_fulfillment_stage@core"
* })
*/
private $active = true;
public function getId(): ?int
{
return $this->id;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(string $label): self
{
$this->label = $label;
return $this;
}
public function getSortIndex(): ?int
{
return $this->sort_index;
}
public function setSortIndex(int $sort_index): self
{
$this->sort_index = $sort_index;
return $this;
}
public function isStartStage(): bool
{
return (bool) $this->is_start_stage;
}
public function setIsStartStage(bool $is_start_stage): self
{
$this->is_start_stage = $is_start_stage;
return $this;
}
public function isCompletionStage(): bool
{
return (bool) $this->is_completion_stage;
}
public function setIsCompletionStage(bool $is_completion_stage): self
{
$this->is_completion_stage = $is_completion_stage;
return $this;
}
public function getBgColor(): ?string
{
return $this->bg_color;
}
public function setBgColor(?string $bg_color): self
{
$this->bg_color = $bg_color;
return $this;
}
public function getWorkNature(): ?string
{
return $this->work_nature;
}
public function setWorkNature(?string $work_nature): self
{
$this->work_nature = $work_nature;
return $this;
}
public function isActive(): bool
{
return (bool) $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
}