self::DURATION_FIXED])] private string $durationSource = self::DURATION_FIXED; #[ORM\Column(name: 'duration_minutes', type: 'smallint', options: ['default' => 0])] private int $durationMinutes = 0; /** بیمار در این بخش حاضر است؟ «انتظار در خانه» نمونهٔ خلافش است. */ #[ORM\Column(name: 'patient_present', type: 'boolean', options: ['default' => true])] private bool $patientPresent = true; /** * با انتخاب چند آیتم، این بخش **یک بار** می‌آید نه چند بار. * «آماده‌سازی» یک بار انجام می‌شود؛ «خود لیزر» به‌ازای هر ناحیه. */ #[ORM\Column(type: 'boolean', options: ['default' => false])] private bool $mergeable = false; #[ORM\Column(name: 'created_at', type: 'integer')] private int $createdAt; /** @var Collection */ #[ORM\OneToMany(targetEntity: SegmentRequirement::class, mappedBy: 'segment', cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection $requirements; public function __construct(ServiceItem $service, int $sequence, string $name) { $this->uuid = Uuid::v4()->toRfc4122(); $this->service = $service; $this->sequence = $sequence; $this->name = $name; $this->createdAt = time(); $this->requirements = new ArrayCollection(); $this->assignTenantPair($service->getSection()->getEntityType(), $service->getSection()->getEntityId()); } public function getId(): ?int { return $this->id; } public function getUuid(): string { return $this->uuid; } public function getService(): ServiceItem { return $this->service; } public function getSequence(): int { return $this->sequence; } public function getName(): string { return $this->name; } public function getDurationSource(): string { return $this->durationSource; } public function getDurationMinutes(): int { return $this->durationMinutes; } public function isPatientPresent(): bool { return $this->patientPresent; } public function isMergeable(): bool { return $this->mergeable; } /** @return Collection */ public function getRequirements(): Collection { return $this->requirements; } public function setPatientPresent(bool $v): self { $this->patientPresent = $v; return $this; } public function setMergeable(bool $v): self { $this->mergeable = $v; return $this; } /** @throws \InvalidArgumentException روی منبع مدت ناشناخته یا مدت ناممکن */ public function setDuration(string $source, int $minutes): self { if (!in_array($source, self::DURATION_SOURCES, true)) { throw new \InvalidArgumentException(sprintf('Unknown duration source "%s".', $source)); } // بخشی که مدتش از آیتم‌ها می‌آید، عدد ثابت لازم ندارد؛ بخش ثابت حتماً دارد. if ($source === self::DURATION_FIXED && $minutes <= 0) { throw new \InvalidArgumentException('A fixed segment needs a positive duration.'); } if ($minutes > self::MAX_TOTAL_MINUTES) { throw new \InvalidArgumentException('Segment duration exceeds the daily cap.'); } $this->durationSource = $source; $this->durationMinutes = max(0, $minutes); return $this; } public function toArray(): array { return [ 'uuid' => $this->uuid, 'service_uuid' => $this->service->getUuid(), 'sequence' => $this->sequence, 'name' => $this->name, 'duration_source' => $this->durationSource, 'duration_minutes' => $this->durationMinutes, 'patient_present' => $this->patientPresent, 'mergeable' => $this->mergeable, 'requirements' => array_map( static fn (SegmentRequirement $r): array => $r->toArray(), $this->requirements->toArray(), ), ]; } }