Files
clinicpro/tests/Representation/DomainCommissionTest.php
T

141 lines
6.0 KiB
PHP

<?php
namespace App\Tests\Representation;
use App\Config\Repository\SiteConfigRepository;
use App\Payment\Entity\Payment;
use App\Representation\Entity\Representation;
use App\Representation\Service\DomainContextResolver;
use App\Settlement\Repository\FinancialBreakdownRepository;
use App\Settlement\Service\CommissionService;
use App\Tests\ApiTestCase;
/**
* قانون کمیسیون دامنه‌محور: کمیسیون فقط وقتی ثبت می‌شود که خرید از دامنه‌ی نماینده
* انجام شده باشد و پزشک/کلینیک هم متعلق به همان نماینده باشد. DomainContextResolver
* تنها نقطه‌ی نگاشت دامنه است.
*/
class DomainCommissionTest extends ApiTestCase
{
private function makeRep(?string $domain = null, bool $global = false, bool $active = true): Representation
{
$owner = $this->createUser(['ROLE_USER', 'ROLE_REPRESENTATION']);
$rep = new Representation($owner, 'نماینده دامنه');
$rep->setCommissionPercent('10');
if ($domain !== null) $rep->setDomain($domain);
$rep->setIsGlobal($global);
$rep->setActive($active);
$this->em->persist($rep);
$this->em->flush();
return $rep;
}
private function makePayment(string $frontendAddress): Payment
{
$payment = new Payment($this->createUser(), 2_000_000, 'mock', Payment::TYPE_APPOINTMENT, $frontendAddress);
$this->em->persist($payment);
$this->em->flush();
return $payment;
}
private function resolver(): DomainContextResolver
{
return static::getContainer()->get(DomainContextResolver::class);
}
// ── DomainContextResolver ────────────────────────────────────────────────
public function testResolverMatchesRepresentationDomainWithNormalization(): void
{
$domain = 'rep-' . uniqid() . '.ir';
$rep = $this->makeRep($domain, global: true);
$ctx = $this->resolver()->resolve('https://www.' . $domain . ':443/payment/result');
$this->assertSame($rep->getId(), $ctx->representationId());
$this->assertTrue($ctx->isGlobalRepresentation);
$this->assertNull($ctx->city);
}
public function testResolverIgnoresInactiveRepresentation(): void
{
$domain = 'rep-' . uniqid() . '.ir';
$this->makeRep($domain, active: false);
$ctx = $this->resolver()->resolve($domain);
$this->assertNull($ctx->representation);
$this->assertFalse($ctx->isGlobalRepresentation);
}
public function testResolverUnknownDomainIsEmpty(): void
{
$ctx = $this->resolver()->resolve('nowhere-' . uniqid() . '.ir');
$this->assertNull($ctx->representation);
$this->assertNull($ctx->city);
}
public function testResolverMatchesByFirstLabelForLocalDev(): void
{
$prefix = 'repdev' . substr(uniqid(), -6);
$rep = $this->makeRep($prefix . '.ir', global: true);
// host لوکال با TLD متفاوت (`.localhost`) باید همان نماینده را بیابد.
$ctx = $this->resolver()->resolve($prefix . '.localhost');
$this->assertSame($rep->getId(), $ctx->representationId());
$this->assertTrue($ctx->isGlobalRepresentation);
}
// ── CommissionService: گارد دوشرطی ───────────────────────────────────────
public function testAppointmentCommissionOnlyWhenDomainOwnerMatchesDoctorOwner(): void
{
static::getContainer()->get(SiteConfigRepository::class)->set('appointment_commission_enabled', '1');
$commission = static::getContainer()->get(CommissionService::class);
$breakdowns = static::getContainer()->get(FinancialBreakdownRepository::class);
$rep = $this->makeRep('rep-' . uniqid() . '.ir');
$other = $this->makeRep('rep-' . uniqid() . '.ir');
// دامنه‌ی نماینده‌ی دیگر → بدون کمیسیون
$p1 = $this->makePayment('https://' . $other->getDomain() . '/payment/result');
$commission->processAppointment($p1, $rep->getId(), $other->getId(), 7);
$this->assertFalse($breakdowns->existsForPayment($p1));
// بدون دامنه (پرداخت بدون frontend_address) → بدون کمیسیون
$p2 = $this->makePayment('');
$commission->processAppointment($p2, $rep->getId(), null, 7);
$this->assertFalse($breakdowns->existsForPayment($p2));
// دامنه و مالک یکی → کمیسیون ثبت می‌شود
$p3 = $this->makePayment('https://' . $rep->getDomain() . '/payment/result');
$commission->processAppointment($p3, $rep->getId(), $rep->getId(), 7);
$this->assertTrue($breakdowns->existsForPayment($p3));
}
public function testSubscriptionCommissionUsesSameDomainGuard(): void
{
$config = static::getContainer()->get(SiteConfigRepository::class);
$config->set('upgrade_commission_enabled', '1');
$config->set('upgrade_commission_percent', '20');
$commission = static::getContainer()->get(CommissionService::class);
$breakdowns = static::getContainer()->get(FinancialBreakdownRepository::class);
$rep = $this->makeRep('rep-' . uniqid() . '.ir');
// نماینده‌ی دامنه معلوم نیست → بدون کمیسیون (رفتار قدیمی کمیسیون می‌داد)
$p1 = $this->makePayment('');
$commission->processSubscription($p1, $rep->getId(), null, 5, null);
$this->assertFalse($breakdowns->existsForPayment($p1));
// دامنه و مالک یکی → کمیسیون
$p2 = $this->makePayment('https://' . $rep->getDomain() . '/panel');
$commission->processSubscription($p2, $rep->getId(), $rep->getId(), 5, null);
$this->assertTrue($breakdowns->existsForPayment($p2));
}
}