feat(discount): admin Discount Management tab + uuid-based rule targets
Switch rule target references from int ids to uuids (frontend-friendly; the engine compares uuids directly) via a migration. Add a Discount Management tab to the subscription page with a full CRUD UI (DiscountTab): table + modal form with per-type dynamic target fields (tenant tag / service cascade / amount / visit count / specific patient / occasion + validity window), priority and combinable/active toggles. Verified TSC + build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -79,15 +79,15 @@ class DiscountRule
|
||||
#[ORM\Column(name: 'valid_to', type: 'integer', nullable: true)]
|
||||
private ?int $validTo = null;
|
||||
|
||||
// ── target fields (بسته به type فقط یکی معنیدار است) ──────────────────────
|
||||
#[ORM\Column(name: 'target_tag_id', type: 'integer', nullable: true)]
|
||||
private ?int $targetTagId = null;
|
||||
// ── target fields (بسته به type فقط یکی معنیدار است؛ uuid برای سازگاری با UI) ──
|
||||
#[ORM\Column(name: 'target_tag_uuid', type: 'string', length: 36, nullable: true)]
|
||||
private ?string $targetTagUuid = null;
|
||||
|
||||
#[ORM\Column(name: 'target_record_id', type: 'integer', nullable: true)]
|
||||
private ?int $targetRecordId = null;
|
||||
#[ORM\Column(name: 'target_record_uuid', type: 'string', length: 36, nullable: true)]
|
||||
private ?string $targetRecordUuid = null;
|
||||
|
||||
#[ORM\Column(name: 'target_service_item_id', type: 'integer', nullable: true)]
|
||||
private ?int $targetServiceItemId = null;
|
||||
#[ORM\Column(name: 'target_service_item_uuid', type: 'string', length: 36, nullable: true)]
|
||||
private ?string $targetServiceItemUuid = null;
|
||||
|
||||
#[ORM\Column(name: 'min_amount_rials', type: 'integer', nullable: true)]
|
||||
private ?int $minAmountRials = null;
|
||||
@@ -128,9 +128,9 @@ class DiscountRule
|
||||
public function isActive(): bool { return $this->active; }
|
||||
public function getValidFrom(): ?int { return $this->validFrom; }
|
||||
public function getValidTo(): ?int { return $this->validTo; }
|
||||
public function getTargetTagId(): ?int { return $this->targetTagId; }
|
||||
public function getTargetRecordId(): ?int { return $this->targetRecordId; }
|
||||
public function getTargetServiceItemId(): ?int { return $this->targetServiceItemId; }
|
||||
public function getTargetTagUuid(): ?string { return $this->targetTagUuid; }
|
||||
public function getTargetRecordUuid(): ?string { return $this->targetRecordUuid; }
|
||||
public function getTargetServiceItemUuid(): ?string { return $this->targetServiceItemUuid; }
|
||||
public function getMinAmountRials(): ?int { return $this->minAmountRials; }
|
||||
public function getMinVisitCount(): ?int { return $this->minVisitCount; }
|
||||
public function getOccasionKind(): ?string { return $this->occasionKind; }
|
||||
@@ -144,9 +144,9 @@ class DiscountRule
|
||||
public function setActive(bool $v): self { $this->active = $v; $this->touch(); return $this; }
|
||||
public function setValidFrom(?int $v): self { $this->validFrom = $v; $this->touch(); return $this; }
|
||||
public function setValidTo(?int $v): self { $this->validTo = $v; $this->touch(); return $this; }
|
||||
public function setTargetTagId(?int $v): self { $this->targetTagId = $v; $this->touch(); return $this; }
|
||||
public function setTargetRecordId(?int $v): self { $this->targetRecordId = $v; $this->touch(); return $this; }
|
||||
public function setTargetServiceItemId(?int $v): self { $this->targetServiceItemId = $v; $this->touch(); return $this; }
|
||||
public function setTargetTagUuid(?string $v): self { $this->targetTagUuid = $v; $this->touch(); return $this; }
|
||||
public function setTargetRecordUuid(?string $v): self { $this->targetRecordUuid = $v; $this->touch(); return $this; }
|
||||
public function setTargetServiceItemUuid(?string $v): self { $this->targetServiceItemUuid = $v; $this->touch(); return $this; }
|
||||
public function setMinAmountRials(?int $v): self { $this->minAmountRials = $v; $this->touch(); return $this; }
|
||||
public function setMinVisitCount(?int $v): self { $this->minVisitCount = $v; $this->touch(); return $this; }
|
||||
public function setOccasionKind(?string $v): self { $this->occasionKind = $v; $this->touch(); return $this; }
|
||||
@@ -166,10 +166,10 @@ class DiscountRule
|
||||
'active' => $this->active,
|
||||
'valid_from' => $this->validFrom,
|
||||
'valid_to' => $this->validTo,
|
||||
'target_tag_id' => $this->targetTagId,
|
||||
'target_record_id' => $this->targetRecordId,
|
||||
'target_service_item_id' => $this->targetServiceItemId,
|
||||
'min_amount_rials' => $this->minAmountRials,
|
||||
'target_tag_uuid' => $this->targetTagUuid,
|
||||
'target_record_uuid' => $this->targetRecordUuid,
|
||||
'target_service_item_uuid' => $this->targetServiceItemUuid,
|
||||
'min_amount_rials' => $this->minAmountRials,
|
||||
'min_visit_count' => $this->minVisitCount,
|
||||
'occasion_kind' => $this->occasionKind,
|
||||
'created_at' => $this->createdAt,
|
||||
|
||||
Reference in New Issue
Block a user