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 = $this->stampTenant(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)); } }