149 lines
6.0 KiB
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());
|
|
}
|
|
}
|