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:
hamed
2026-07-17 12:02:03 +03:30
co-authored by Claude Fable 5
parent b3b1dad832
commit 18d9cc9812
8 changed files with 451 additions and 39 deletions
+4 -4
View File
@@ -7,11 +7,11 @@ Owner is resolved from the authenticated user (`ROLE_DOCTOR` → doctor, `ROLE_C
| type | target field(s) | meaning |
|------|-----------------|---------|
| `patient_tag` | `target_tag_id` (TenantTag id) | patient carries the tag |
| `patient_tag` | `target_tag_uuid` (TenantTag uuid) | patient carries the tag |
| `invoice_amount` | `min_amount_rials` | session `final_price_rials` ≥ threshold |
| `specific_patient` | `target_record_id` (PatientRecord id) | a specific patient's record |
| `specific_patient` | `target_record_uuid` (PatientRecord uuid) | a specific patient's record |
| `occasion` | `valid_from`/`valid_to`, optional `occasion_kind: birthday` | date window; `birthday` also requires today == patient birthday (month/day) |
| `service` | `target_service_item_id` (ServiceItem id) | session contains that service (discount base = that service's line total) |
| `service` | `target_service_item_uuid` (ServiceItem uuid) | session contains that service (discount base = that service's line total) |
| `visit_count` | `min_visit_count` | patient's session count ≥ threshold |
Shared fields: `discount_type` (`percent`|`fixed`), `value` (percent 0..100 or rials), `priority` (int, higher first), `combinable` (bool), `active` (bool), `valid_from`/`valid_to` (unix, nullable).
@@ -40,7 +40,7 @@ Create a rule. **Auth:** doctor/clinic.
| `combinable` | bool | ❌ | default false |
| `active` | bool | ❌ | default true |
| `valid_from` / `valid_to` | int (unix) | ❌ | validity window |
| `target_tag_id` / `target_record_id` / `target_service_item_id` | int | ❌ | per-type target |
| `target_tag_uuid` / `target_record_uuid` / `target_service_item_uuid` | string (uuid) | ❌ | per-type target |
| `min_amount_rials` / `min_visit_count` | int | ❌ | per-type threshold |
| `occasion_kind` | string | ❌ | `birthday` or null |