DetailsStep now renders the appointment's visit date/time first (from
session_at, falling back to created_at) and an itemized cost table (visit +
each service line with its line total) plus the grand total. Extend
SessionCardData with session_at, services_total_rials, and per-line price
fields already returned by the session API.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Introduced a new boolean flag `require_visit_price` in the `EntityInsurancePricing` to enforce visit price for appointments.
- Updated the appointment creation endpoints to validate `visit_price_rials` based on the new flag.
- Added `visit_price_rials` field to the `Appointment` entity to store the visit price.
- Enhanced the `PatientService` to validate visit price during session creation.
- Updated API documentation to reflect changes in appointment and insurance pricing.
- Implemented a new service `VisitPriceRequirementResolver` to determine if a visit price is required for a doctor based on their pricing settings.
- Added migrations to update the database schema for the new fields.
SessionStepper copied MUI's LTR connector offsets (left: -50%), which in
the RTL admin drew each connector away from its previous step — a stray
line ran off the card edge past the last step and the first two steps
had no line between them. Swap the offsets so connectors extend toward
the previous step on the right, matching tauri's MUI-flipped rendering.
The acceptance-time field showed two clock icons (custom ClockP + the
browser's native picker indicator); hide the native one like the tauri
source, which has a single ClockField adornment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The admin SPA never called POST /billing/invoices, so every session had
invoice_uuid = null and the view-invoice buttons on the patient services
tab (and MyPatients visit modal) were permanently disabled. Add a shared
useIssueInvoice hook (idempotent create + finalize when draft) and wire
it into:
- DetailsStep: the wizard's final step now really issues the invoice
- SessionServiceCard / PatientDetailPage: clicking view-invoice on a
session without an invoice issues it first, then opens the summary
- MyPatientsPage visit modal: same, replacing the dead disabled button
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backend:
- Add session_at and inventory_package_id to patient_sessions, new
session_consumables table (migration Version20260716102537)
- New SessionConsumable entity/repository mirroring SessionService;
price snapshot, quantity >= 1, tenant-scoped silent skip
- PatientService::createSession accepts session_at, consumables[] and
inventory_package_uuid; consumables are fully patient-paid (no
insurance coverage) and added to final_price_rials
- Functional tests: success, foreign-tenant/unknown skip, empty and
zero-quantity edges (tests/Patient/SessionConsumableTest.php)
- docs/api/patient.md updated for the new Create Session fields
Frontend (admin):
- NewSessionPage rewritten as the tauri /files/create-service 3-step
wizard (ایجاد سرویس ← پرداخت ← جزییات) using SessionStepper
- New CreateStep: acceptance date/time (Jalali), section/service/staff,
consumables with counters, package select, conditional insurance
block (insured service or insured patient profile), price summary
- PaymentStep/DetailsStep extracted from SessionPaymentPage and shared
between both pages (behavior unchanged, tests still green)
- UserTick and FilesServiceAddCard icons ported verbatim from tauri
- Vitest coverage for the wizard incl. empty-data states
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>