Files
clinicpro/tests/Billing/ConfirmedAppointmentAppearsInPaymentsTest.php
T

148 lines
6.0 KiB
PHP

<?php
namespace App\Tests\Billing;
use App\Appointment\Entity\Appointment;
use App\Billing\Entity\Invoice;
use App\Doctor\Entity\Doctor;
use App\Tests\ApiTestCase;
/**
* نوبتی که از پنل قطعی و پولش ثبت می‌شود باید در «پرداخت‌ها» دیده شود.
*
* فهرست پرداخت‌ها صورتحساب‌محور است و صورتحساب فقط برای مراجعهٔ بیمه‌دار ساخته
* می‌شد؛ نتیجه‌اش این بود که پرداختِ نوبتِ بدون بیمه هیچ‌جا دیده نمی‌شد.
*/
class ConfirmedAppointmentAppearsInPaymentsTest extends ApiTestCase
{
private function makeDoctor(): Doctor
{
$user = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
$doctor = new Doctor($user, 'دکتر تست');
$doctor->setMobileNumber($user->getMobileNumber());
$this->em->persist($doctor);
$this->em->flush();
return $doctor;
}
private function makeAppointment(Doctor $doctor, int $visitPriceRials = 5_000_000): Appointment
{
$start = strtotime('+30 days') + random_int(0, 500_000) * 7;
$appointment = $this->newAppointment($doctor, $this->createUser(), $start, $start + 900);
$appointment->setVisitPriceRials($visitPriceRials);
$this->em->persist($appointment);
$this->em->flush();
return $appointment;
}
/** @return array<int, array<string, mixed>> ردیف‌های فهرست پرداخت‌های همان پزشک */
private function payments(Doctor $doctor): array
{
$body = $this->authJson('GET', '/api/v1/my/billing/payments?limit=100', $doctor->getUser());
self::assertSame(200, $this->responseCode());
return $body['data'] ?? [];
}
public function testPartialPaymentOnConfirmShowsUpInThePaymentsList(): void
{
$doctor = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
self::assertSame([], $this->payments($doctor));
$this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
'payments' => [['method' => 'cash', 'amount_rials' => 1_000_000]],
]);
self::assertSame(200, $this->responseCode());
$rows = $this->payments($doctor);
self::assertCount(1, $rows);
self::assertSame(5_000_000, $rows[0]['amount_rials']);
self::assertSame(1_000_000, $rows[0]['paid_rials']);
self::assertSame('partial', $rows[0]['status']);
}
public function testFullPaymentOnConfirmIsListedAsPaid(): void
{
$doctor = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
$this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
'payments' => [['method' => 'pos', 'amount_rials' => 5_000_000]],
]);
$rows = $this->payments($doctor);
self::assertCount(1, $rows);
self::assertSame('paid', $rows[0]['status']);
}
/** صورتحساب باید نهایی باشد، وگرنه فهرست پرداخت‌ها آن را فیلتر می‌کند. */
public function testTheGeneratedInvoiceIsFinalized(): void
{
$doctor = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
$res = $this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
'payments' => [['method' => 'cash', 'amount_rials' => 2_000_000]],
]);
$this->em->clear();
$invoices = $this->em->getRepository(Invoice::class)->findBy(['entityId' => $doctor->getId(), 'entityType' => 'doctor']);
self::assertCount(1, $invoices);
self::assertSame(Invoice::STATUS_FINALIZED, $invoices[0]->getStatus());
self::assertSame($res['data']['session']['uuid'] !== null, true);
}
/** مرزی: قطعی‌کردن بدون پرداخت سندی نمی‌سازد — همان رفتار قبلی. */
public function testConfirmWithoutPaymentCreatesNoInvoice(): void
{
$doctor = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
$this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
]);
self::assertSame(200, $this->responseCode());
self::assertSame([], $this->payments($doctor));
}
/** خطا: پرداخت بیشتر از مبلغ نوبت رد می‌شود و صورتحسابی هم نمی‌ماند. */
public function testOverpaymentIsRejectedAndLeavesNoInvoice(): void
{
$doctor = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
$this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
'payments' => [['method' => 'cash', 'amount_rials' => 9_000_000]],
]);
self::assertSame(422, $this->responseCode());
self::assertSame([], $this->payments($doctor));
}
/** پرداخت‌های یک پزشک نباید در فهرست پزشک دیگر بیاید. */
public function testPaymentsStayInsideTheirTenant(): void
{
$doctor = $this->makeDoctor();
$other = $this->makeDoctor();
$appointment = $this->makeAppointment($doctor);
$this->authJson('POST', "/api/v1/appointment/{$appointment->getUuid()}/confirm", $doctor->getUser(), [
'version' => $appointment->getVersion(),
'payments' => [['method' => 'cash', 'amount_rials' => 1_000_000]],
]);
self::assertCount(1, $this->payments($doctor));
self::assertSame([], $this->payments($other));
}
}