$serviceItems قیمت کل هر ردیف (با احتساب تعداد) */ public function calculateFinalPrice( int $visitPrice, float $baseDiscount, float $suppDiscount, array $serviceItems, string $entityType = 'doctor', int $entityId = 0, ?int $baseInsuranceId = null, ?int $suppInsuranceId = null, ): array { $afterBase = $visitPrice * (1 - $baseDiscount / 100); $afterSupp = $afterBase * (1 - $suppDiscount / 100); $visitShare = (int) round($afterSupp); $servicesTotal = 0; $servicesPatient = 0; foreach ($serviceItems as $svc) { $servicesTotal += $svc['price_rials']; $baseRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $baseInsuranceId, $svc['item_id']); $suppRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $suppInsuranceId, $svc['item_id']); $breakdown = $this->billingCalculator->calculateItem(new Money($svc['price_rials']), $baseRule, $suppRule); $servicesPatient += $breakdown->patientRials; } return [ 'services_total_rials' => $servicesTotal, 'final_price_rials' => $visitShare + $servicesPatient, ]; } public function autoCreateOnAppointmentConfirm(Appointment $appointment): void { $doctor = $appointment->getDoctor(); // پرونده‌ی پزشک $this->autoCreateForEntity('doctor', $doctor->getId(), $appointment, $doctor->getId()); // کلینیک نوبت را تعیین کن: اول از آدرس انتخاب‌شده، وگرنه اگر دکتر فقط عضو یک کلینیک باشد. $clinicId = null; $addressId = $appointment->getAddressId(); if ($addressId !== null) { $clinicId = $this->addressRepo->find($addressId)?->getClinicId(); } if ($clinicId === null) { $clinics = $this->clinicRepo->findByDoctor($doctor); if (count($clinics) === 1) { $clinicId = $clinics[0]->getId(); } } if ($clinicId !== null) { $this->autoCreateForEntity('clinic', $clinicId, $appointment, $clinicId); } } private function autoCreateForEntity(string $entityType, int $entityId, Appointment $appointment, int $createdById): void { if (!$this->subscriptionService->hasFeature($entityType, $entityId, 'patient_records')) { return; } $patient = $appointment->getUser(); $record = $this->recordRepo->findByEntityAndUser($entityType, $entityId, $patient); if ($record === null) { $record = new PatientRecord($entityType, $entityId, $patient, 'system', $createdById); $this->recordRepo->save($record); } $session = new PatientSession($record, $appointment); $this->sessionRepo->save($session); } public function createSession( PatientRecord $record, array $data, string $entityType, int $entityId ): PatientSession { $session = new PatientSession($record); if (!empty($data['appointment_uuid'])) { // appointment را از بیرون resolve می‌کنند و session را ست می‌کنند } $session->setInsuranceBaseId(isset($data['insurance_base_id']) ? (int) $data['insurance_base_id'] : null); $session->setInsuranceSupplementaryId(isset($data['insurance_supplementary_id']) ? (int) $data['insurance_supplementary_id'] : null); $session->setVisitPriceRials((int) ($data['visit_price_rials'] ?? 0)); $session->setBaseInsuranceDiscountPercent((float) ($data['base_insurance_discount_percent'] ?? 0)); $session->setSupplementaryDiscountPercent((float) ($data['supplementary_discount_percent'] ?? 0)); $session->setPaymentMethod($data['payment_method'] ?? 'pending'); $session->setNotes($data['notes'] ?? null); // جمع‌آوری service items (با احتساب تعداد) $serviceItemsData = []; foreach (($data['services'] ?? []) as $svc) { $item = $this->serviceItemRepo->findByUuid($svc['service_item_uuid'] ?? ''); if ($item !== null) { $qty = max(1, (int) ($svc['quantity'] ?? 1)); $serviceItemsData[] = ['item_id' => $item->getId(), 'price_rials' => $item->getPriceRials() * $qty]; } } $priceCalc = $this->calculateFinalPrice( $session->getVisitPriceRials(), $session->getBaseInsuranceDiscountPercent(), $session->getSupplementaryDiscountPercent(), $serviceItemsData, $entityType, $entityId, $session->getInsuranceBaseId(), $session->getInsuranceSupplementaryId(), ); $session->setServicesTotalRials($priceCalc['services_total_rials']); $session->setFinalPriceRials($priceCalc['final_price_rials']); $this->sessionRepo->save($session); // ثبت session services foreach (($data['services'] ?? []) as $svc) { $item = $this->serviceItemRepo->findByUuid($svc['service_item_uuid'] ?? ''); if ($item === null) { continue; } $staff = !empty($svc['staff_uuid']) ? $this->staffRepo->findByUuid($svc['staff_uuid']) : null; $qty = max(1, (int) ($svc['quantity'] ?? 1)); $ss = new SessionService($session, $item, $staff, $qty); $this->sessionServiceRepo->save($ss); $session->addService($ss); } return $session; } }