feat(discount): add DiscountRule entity and session discount-rule audit columns

New Discount domain: DiscountRule (generic per-tenant rule with 6 types,
priority, combinable, validity window, and per-type target fields) plus its
repository. PatientSession gains applied_discount_rule_id/label audit columns
and setDiscount() now records the source rule. Migration creates the table
and columns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-17 11:47:33 +03:30
co-authored by Claude Fable 5
parent db7b0aca1a
commit f0e1f43d51
4 changed files with 274 additions and 1 deletions
+15 -1
View File
@@ -76,6 +76,14 @@ class PatientSession
#[ORM\Column(name: 'discount_rials', type: 'integer')]
private int $discountRials = 0;
/** منبع تخفیف: id قانون تخفیف اعمال‌شده (audit)؛ null اگر دستی یا بدون تخفیف */
#[ORM\Column(name: 'applied_discount_rule_id', type: 'integer', nullable: true)]
private ?int $appliedDiscountRuleId = null;
/** کشِ نام قانون اعمال‌شده برای نمایش/گزارش بدون join */
#[ORM\Column(name: 'applied_discount_rule_label', type: 'string', length: 120, nullable: true)]
private ?string $appliedDiscountRuleLabel = null;
/** زمان تسویه‌ی کامل (unix)؛ تا قبل از صفر شدن بدهی null است */
#[ORM\Column(name: 'paid_at', type: 'integer', nullable: true)]
private ?int $paidAt = null;
@@ -193,14 +201,18 @@ class PatientSession
public function setServicesTotalRials(int $v): self { $this->servicesTotalRials = $v; $this->updatedAt = time(); return $this; }
public function setFinalPriceRials(int $v): self { $this->finalPriceRials = $v; $this->updatedAt = time(); return $this; }
public function setPaymentMethod(string $v): self { $this->paymentMethod = $v; $this->updatedAt = time(); return $this; }
public function setDiscount(?string $type, int $value, int $rials): self
public function setDiscount(?string $type, int $value, int $rials, ?int $ruleId = null, ?string $ruleLabel = null): self
{
$this->discountType = $type;
$this->discountValue = $type === null ? 0 : $value;
$this->discountRials = $type === null ? 0 : $rials;
$this->appliedDiscountRuleId = $type === null ? null : $ruleId;
$this->appliedDiscountRuleLabel = $type === null ? null : $ruleLabel;
$this->updatedAt = time();
return $this;
}
public function getAppliedDiscountRuleId(): ?int { return $this->appliedDiscountRuleId; }
public function getAppliedDiscountRuleLabel(): ?string { return $this->appliedDiscountRuleLabel; }
public function setSessionAt(?int $v): self { $this->sessionAt = $v; $this->updatedAt = time(); return $this; }
public function setInventoryPackage(?InventoryPackage $v): self { $this->inventoryPackage = $v; $this->updatedAt = time(); return $this; }
public function setPaidAt(?int $v): self { $this->paidAt = $v; $this->updatedAt = time(); return $this; }
@@ -226,6 +238,8 @@ class PatientSession
'discount_type' => $this->discountType,
'discount_value' => $this->discountValue,
'discount_rials' => $this->discountRials,
'applied_discount_rule_id' => $this->appliedDiscountRuleId,
'applied_discount_rule_label' => $this->appliedDiscountRuleLabel,
'paid_at' => $this->paidAt,
'paid_total_rials' => $this->getPaidTotalRials(),
'payments' => array_map(