createUser(['ROLE_CLINIC']); $clinic = new Clinic($owner); $this->em->persist($clinic); $doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر تست'); $this->em->persist($doctor); $clinic->getDoctors()->add($doctor); $this->em->persist(new UserActiveContext($owner, $clinic->getUuid(), 'clinic')); $patient = $this->createUser(['ROLE_USER']); $patient->setRealName('بیمار تست'); $record = new PatientRecord('clinic', $clinic->getId(), $patient, 'clinic', $clinic->getId()); $this->em->persist($record); $section = new ServiceSection('clinic', $clinic->getId(), 'لیزر'); $this->em->persist($section); $this->em->flush(); return [$owner, $clinic, $record, $section]; } private function service(ServiceSection $section, string $name, int $priceRials): ServiceItem { $item = new ServiceItem($section, $name); $item->setPriceRials($priceRials); $this->em->persist($item); $this->em->flush(); return $item; } private function invoiceOf(PatientSession $session): ?Invoice { $this->em->clear(); return $this->em->getRepository(Invoice::class)->findOneBy(['patientSessionId' => $session->getId()]); } /** ✅ موفق: افزودن سرویس به مراجعه، مبلغ صورتحساب را هم بالا می‌برد. */ public function testEditingSessionServicesUpdatesTheInvoiceTotal(): void { [$owner, , $record, $section] = $this->scenario(); $first = $this->service($section, 'لیزر ناحیه‌ای', 10_000_000); $second = $this->service($section, 'لیزر توتال', 13_000_000); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'services' => [['service_item_uuid' => $first->getUuid(), 'quantity' => 1]], ]); self::assertSame(201, $this->responseCode()); $sessionUuid = $created['data']['uuid']; // صورتحساب از مسیر پرداخت ساخته می‌شود (مراجعهٔ بدون بیمه). $this->authJson('POST', '/api/v1/billing/invoices', $owner, ['session_uuid' => $sessionUuid]); self::assertSame(201, $this->responseCode()); $session = $this->em->getRepository(PatientSession::class)->findOneBy(['uuid' => $sessionUuid]); self::assertSame(10_000_000, $this->invoiceOf($session)->getTotalRials()); // ویرایش: سرویس دوم اضافه می‌شود. $this->authJson('PATCH', '/api/v1/session/' . $sessionUuid, $owner, [ 'services' => [ ['service_item_uuid' => $first->getUuid(), 'quantity' => 1], ['service_item_uuid' => $second->getUuid(), 'quantity' => 1], ], ]); self::assertSame(200, $this->responseCode()); $session = $this->em->getRepository(PatientSession::class)->findOneBy(['uuid' => $sessionUuid]); $invoice = $this->invoiceOf($session); self::assertSame(23_000_000, $invoice->getTotalRials()); self::assertSame(23_000_000, $invoice->getPatientRials()); self::assertCount(2, $invoice->getItems()); } /** ⚠️ مرزی: حذف سرویس هم باید مبلغ را پایین بیاورد، نه اینکه خط یتیم بماند. */ public function testRemovingAServiceShrinksTheInvoice(): void { [$owner, , $record, $section] = $this->scenario(); $first = $this->service($section, 'سرویس اول', 5_000_000); $second = $this->service($section, 'سرویس دوم', 7_000_000); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'services' => [ ['service_item_uuid' => $first->getUuid(), 'quantity' => 1], ['service_item_uuid' => $second->getUuid(), 'quantity' => 1], ], ]); $sessionUuid = $created['data']['uuid']; $this->authJson('POST', '/api/v1/billing/invoices', $owner, ['session_uuid' => $sessionUuid]); $this->authJson('PATCH', '/api/v1/session/' . $sessionUuid, $owner, [ 'services' => [['service_item_uuid' => $first->getUuid(), 'quantity' => 1]], ]); self::assertSame(200, $this->responseCode()); $session = $this->em->getRepository(PatientSession::class)->findOneBy(['uuid' => $sessionUuid]); $invoice = $this->invoiceOf($session); self::assertSame(5_000_000, $invoice->getTotalRials()); self::assertCount(1, $invoice->getItems()); } /** ⚠️ مرزی: مراجعهٔ بدونِ صورتحساب نباید با ویرایش، صورتحساب بگیرد. */ public function testSessionWithoutInvoiceStaysWithoutOne(): void { [$owner, , $record, $section] = $this->scenario(); $item = $this->service($section, 'سرویس', 4_000_000); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [ 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 1]], ]); $sessionUuid = $created['data']['uuid']; $this->authJson('PATCH', '/api/v1/session/' . $sessionUuid, $owner, [ 'services' => [['service_item_uuid' => $item->getUuid(), 'quantity' => 2]], ]); self::assertSame(200, $this->responseCode()); $session = $this->em->getRepository(PatientSession::class)->findOneBy(['uuid' => $sessionUuid]); self::assertNull($this->invoiceOf($session)); } }