feat: add visit price requirement feature

- 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.
This commit is contained in:
hamed
2026-07-16 19:44:30 +03:30
parent 880c4c06cb
commit a0ddb4c0d1
18 changed files with 497 additions and 22 deletions
@@ -12,6 +12,7 @@ use App\Auth\Repository\UserActiveContextRepository;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Entity\Doctor;
use App\Doctor\Repository\DoctorRepository;
use App\Insurance\Service\VisitPriceRequirementResolver;
use App\Patient\Service\PatientResolver;
use App\Secretary\Entity\DoctorSecretary;
use App\Secretary\Repository\DoctorSecretaryRepository;
@@ -42,6 +43,7 @@ class MyAppointmentsController extends BaseController
private readonly PatientResolver $patientResolver,
private readonly \App\Auth\Repository\UserRepository $userRepo,
private readonly \App\UserProfile\Repository\UserProfileRepository $profileRepo,
private readonly VisitPriceRequirementResolver $visitPriceResolver,
) {}
#[Route('/api/v1/my/appointment', methods: ['POST'])]
@@ -127,6 +129,11 @@ class MyAppointmentsController extends BaseController
return $this->error(ErrorCodes::FORBIDDEN, 'برای این پزشک مجاز به ثبت نوبت نیستید', 403);
}
$visitPriceRials = isset($data['visit_price_rials']) ? (int) $data['visit_price_rials'] : null;
if ($this->visitPriceResolver->isRequiredForDoctor($doctor) && ($visitPriceRials ?? 0) <= 0) {
return $this->error(ErrorCodes::VALIDATION, 'هزینه ویزیت الزامی است', 422, 'visit_price_rials');
}
// Identity is keyed on the national code (unique) so the case-file stays
// single per person even when booked under a different mobile.
$patient = $this->patientResolver->resolveForBooking($nationalCode, $mobile, $patientName);
@@ -163,6 +170,9 @@ class MyAppointmentsController extends BaseController
if (isset($data['deposit_amount_rials'])) {
$appointment->setDepositAmountRials((int) $data['deposit_amount_rials']);
}
if ($visitPriceRials !== null) {
$appointment->setVisitPriceRials($visitPriceRials);
}
// The resolver returns the patient keyed on national code, so its profile
// name is the real identity. Snapshot that (not the free-typed modal name)
// so the appointment never diverges from an existing profile; fall back to