fix(admin): drop cached environment data when switching context
A doctor who also owns a clinic runs two environments, and a subscription belongs to an environment, not to the user. The panel treated it as the user's: the subscription query was keyed ['subscription-my'] with no context, and switching environments never touched the react-query cache. So upgrading the clinic left the personal practice showing the clinic's plan with its feature-gated menu items unlocked, and vice versa. The query key now carries the active dbUuid, and the context switch clears the whole cache — every cached response belongs to the environment it was fetched in, not just this one. The API was already correct: DualEnvironmentSubscriptionTest pins that granting one environment leaves the other on free. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Subscription;
|
||||
|
||||
use App\Auth\Entity\User;
|
||||
use App\Auth\Entity\UserActiveContext;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Shared\Context\EntityContext;
|
||||
use App\Subscription\Entity\SubscriptionPeriod;
|
||||
use App\Subscription\Entity\SubscriptionPlan;
|
||||
use App\Subscription\Service\SubscriptionService;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* A doctor who also owns a clinic runs two environments. Upgrading one must not
|
||||
* upgrade the other: the subscription belongs to the environment, not the user.
|
||||
*/
|
||||
class DualEnvironmentSubscriptionTest extends ApiTestCase
|
||||
{
|
||||
private function makeUserWithBothEnvironments(): array
|
||||
{
|
||||
$user = $this->createUser(['ROLE_DOCTOR', 'ROLE_CLINIC']);
|
||||
|
||||
$doctor = new Doctor($user, 'دکتر تست');
|
||||
$this->em->persist($doctor);
|
||||
|
||||
$clinic = new Clinic($user);
|
||||
$clinic->setName('کلینیک تست');
|
||||
$this->em->persist($clinic);
|
||||
$this->em->flush();
|
||||
|
||||
return [$user, $doctor, $clinic];
|
||||
}
|
||||
|
||||
private function makePeriod(): SubscriptionPeriod
|
||||
{
|
||||
$plan = new SubscriptionPlan('pro-' . bin2hex(random_bytes(4)), 5, 2, ['patient_records' => true]);
|
||||
$this->em->persist($plan);
|
||||
|
||||
$period = new SubscriptionPeriod($plan, 'سه ماهه', 3, 1_000_000);
|
||||
$this->em->persist($period);
|
||||
$this->em->flush();
|
||||
|
||||
return $period;
|
||||
}
|
||||
|
||||
private function setActiveContext(User $user, string $dbUuid, string $dbType): void
|
||||
{
|
||||
$this->em->persist(new UserActiveContext($user, $dbUuid, $dbType));
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
private function service(): SubscriptionService
|
||||
{
|
||||
return static::getContainer()->get(SubscriptionService::class);
|
||||
}
|
||||
|
||||
public function testGrantingTheClinicLeavesThePersonalPracticeOnFree(): void
|
||||
{
|
||||
[$user, $doctor, $clinic] = $this->makeUserWithBothEnvironments();
|
||||
$period = $this->makePeriod();
|
||||
|
||||
$this->service()->grant('clinic', $clinic->getId(), $period->getUuid(), $user);
|
||||
|
||||
self::assertSame(
|
||||
$period->getPlan()->getId(),
|
||||
$this->service()->getEffectivePlan('clinic', $clinic->getId())?->getId(),
|
||||
);
|
||||
self::assertSame('free', $this->service()->getEffectivePlan('doctor', $doctor->getId())?->getName());
|
||||
self::assertNull($this->service()->getActiveSubscription('doctor', $doctor->getId()));
|
||||
}
|
||||
|
||||
public function testMyReportsTheClinicPlanOnlyWhileStandingInTheClinic(): void
|
||||
{
|
||||
[$user, $doctor, $clinic] = $this->makeUserWithBothEnvironments();
|
||||
$period = $this->makePeriod();
|
||||
$this->service()->grant('clinic', $clinic->getId(), $period->getUuid(), $user);
|
||||
|
||||
$this->setActiveContext($user, $clinic->getUuid(), EntityContext::TYPE_CLINIC);
|
||||
$body = $this->authJson('GET', '/api/v1/subscription/my', $user);
|
||||
self::assertSame($period->getPlan()->getName(), $body['data']['effective_plan']['name']);
|
||||
self::assertNotNull($body['data']['subscription']);
|
||||
}
|
||||
|
||||
public function testMyFallsBackToFreeWhileStandingInThePersonalPractice(): void
|
||||
{
|
||||
[$user, $doctor, $clinic] = $this->makeUserWithBothEnvironments();
|
||||
$period = $this->makePeriod();
|
||||
$this->service()->grant('clinic', $clinic->getId(), $period->getUuid(), $user);
|
||||
|
||||
$this->setActiveContext($user, $doctor->getUuid(), EntityContext::TYPE_DOCTOR);
|
||||
$body = $this->authJson('GET', '/api/v1/subscription/my', $user);
|
||||
self::assertSame('free', $body['data']['effective_plan']['name']);
|
||||
self::assertNull($body['data']['subscription']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user