Files
clinicpro/tests/Payment/PayerSeesOwnPaymentTest.php

149 lines
6.0 KiB
PHP

<?php
namespace App\Tests\Payment;
use App\Appointment\Entity\Appointment;
use App\Auth\Entity\User;
use App\Auth\Entity\UserActiveContext;
use App\Doctor\Entity\Doctor;
use App\Payment\Entity\Payment;
use App\Shared\Context\EntityContext;
use App\Tests\ApiTestCase;
/**
* پرداخت‌کننده باید پرداخت خودش را ببیند، حتی وقتی خودش صاحب یک محیط دیگر است.
*
* پرداختِ بیمار به محیطِ پزشکِ مقصد تعلق دارد. `TenantFilterSubscriber` برای کاربری
* که محیط حل‌شده دارد فیلتر را روشن می‌کند، و چون `Payment` محیط‌دار است، پزشکی که
* از مطب دیگری نوبت گرفته بود صفحهٔ نتیجهٔ پرداخت خودش را ۴۰۴ می‌گرفت.
*/
class PayerSeesOwnPaymentTest extends ApiTestCase
{
/**
* پزشکی که محیط کاریِ فعالش هم ذخیره شده است.
*
* بدون این ردیف، `EntityContextResolver` محیط را «انتخاب‌شده» نمی‌داند و
* `TenantFilterSubscriber` فیلتر را روشن نمی‌کند — یعنی تست باگ را نمی‌بیند،
* درحالی‌که کاربر واقعی که وارد پنل شده آن را می‌گیرد.
*/
private function makeDoctor(string $name): Doctor
{
$user = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
$doctor = new Doctor($user, $name);
$doctor->setMobileNumber($user->getMobileNumber());
$this->em->persist($doctor);
$this->em->flush();
$this->em->persist(new UserActiveContext($user, $doctor->getUuid(), EntityContext::TYPE_DOCTOR));
$this->em->flush();
return $doctor;
}
/** پرداختی که «پزشکِ پرداخت‌کننده» برای نوبتِ «پزشکِ مقصد» انجام داده است. */
private function makeCrossTenantPayment(Doctor $target, User $payer): Payment
{
$start = strtotime('+20 days') + random_int(0, 500_000) * 7;
$appointment = $this->newAppointment($target, $payer, $start, $start + 900);
$appointment->setVisitPriceRials(1_500_000);
$this->em->persist($appointment);
$this->em->flush();
$payment = new Payment($payer, 1_500_000, 'mellat', Payment::TYPE_APPOINTMENT, '');
$payment->setAppointment($appointment);
$payment->assignTenant(EntityContext::forBooking($target, null));
$this->em->persist($payment);
$this->em->flush();
return $payment;
}
public function testDoctorSeesThePaymentHeMadeAtAnotherPractice(): void
{
$target = $this->makeDoctor('پزشک مقصد');
$payer = $this->makeDoctor('پزشک پرداخت‌کننده');
$payment = $this->makeCrossTenantPayment($target, $payer->getUser());
$body = $this->authJson('GET', '/api/v1/payment/' . $payment->getUuid(), $payer->getUser());
self::assertSame(200, $this->responseCode());
self::assertSame($payment->getUuid(), $body['data']['uuid']);
}
public function testTheSamePaymentAppearsInHisPaymentsList(): void
{
$target = $this->makeDoctor('پزشک مقصد');
$payer = $this->makeDoctor('پزشک پرداخت‌کننده');
$payment = $this->makeCrossTenantPayment($target, $payer->getUser());
$body = $this->authJson('GET', '/api/v1/my/payments?limit=100', $payer->getUser());
self::assertSame(200, $this->responseCode());
self::assertContains(
$payment->getUuid(),
array_column($body['data'], 'uuid'),
'پرداختِ خودِ کاربر باید در فهرست پرداخت‌هایش باشد',
);
}
/** بیمار ساده — بدون محیط — از قبل هم کار می‌کرد و نباید بشکند. */
public function testPlainPatientStillSeesHisPayment(): void
{
$target = $this->makeDoctor('پزشک مقصد');
$patient = $this->createUser();
$payment = $this->makeCrossTenantPayment($target, $patient);
$body = $this->authJson('GET', '/api/v1/payment/' . $payment->getUuid(), $patient);
self::assertSame(200, $this->responseCode());
self::assertSame($payment->getUuid(), $body['data']['uuid']);
}
/** دورزدنِ فیلتر نباید به معنی بازشدن پرداختِ دیگران باشد. */
public function testAnotherUserIsStillForbidden(): void
{
$target = $this->makeDoctor('پزشک مقصد');
$payer = $this->createUser();
$stranger = $this->createUser();
$payment = $this->makeCrossTenantPayment($target, $payer);
$this->authJson('GET', '/api/v1/payment/' . $payment->getUuid(), $stranger);
self::assertSame(403, $this->responseCode());
}
/**
* همان الگو روی نوبت: نوبتی که کاربر به‌عنوان بیمار گرفته، در محیطِ پزشکِ مقصد
* ثبت می‌شود و برای کاربرِ صاحبِ محیطِ دیگر نامرئی می‌شد.
*/
public function testDoctorSeesTheAppointmentHeBookedAtAnotherPractice(): void
{
$target = $this->makeDoctor('پزشک مقصد');
$payer = $this->makeDoctor('پزشک بیمار');
$payment = $this->makeCrossTenantPayment($target, $payer->getUser());
$body = $this->authJson('GET', '/api/v1/appointments/user', $payer->getUser());
self::assertSame(200, $this->responseCode());
self::assertContains(
$payment->getAppointment()->getUuid(),
array_column($body['data']['data'] ?? $body['data'], 'uuid'),
'نوبتِ خودِ کاربر باید در فهرست نوبت‌هایش باشد',
);
}
public function testUnknownPaymentIsStillNotFound(): void
{
$user = $this->createUser();
$this->authJson('GET', '/api/v1/payment/00000000-0000-4000-8000-000000000000', $user);
self::assertSame(404, $this->responseCode());
}
}