feat: implement staff management and subscription system

- Added StaffController for managing clinic staff, including listing, creating, updating, and toggling staff status.
- Created ClinicStaff entity and repository for staff data handling.
- Developed SubscriptionController to manage subscription plans and periods, including trial subscriptions.
- Introduced SubscriptionPlan, SubscriptionPeriod, and ClinicSubscription entities for subscription management.
- Implemented SubscriptionService for handling subscription logic, including trial activation and subscription creation from payments.
- Added necessary repositories for subscription entities to facilitate data access and manipulation.
This commit is contained in:
hamed
2026-06-14 22:10:28 +03:30
parent dcd631f503
commit b0244f28f5
53 changed files with 4434 additions and 40 deletions
@@ -0,0 +1,56 @@
<?php
namespace App\Subscription\Repository;
use App\Subscription\Entity\ClinicSubscription;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class ClinicSubscriptionRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ClinicSubscription::class);
}
public function findByUuid(string $uuid): ?ClinicSubscription
{
return $this->findOneBy(['uuid' => $uuid]);
}
public function findActive(string $entityType, int $entityId): ?ClinicSubscription
{
return $this->createQueryBuilder('s')
->where('s.entityType = :type')
->andWhere('s.entityId = :id')
->andWhere('s.expiresAt IS NULL OR s.expiresAt > :now')
->setParameter('type', $entityType)
->setParameter('id', $entityId)
->setParameter('now', time())
->orderBy('s.id', 'DESC')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
public function hasUsedTrial(string $entityType, int $entityId): bool
{
$count = $this->createQueryBuilder('s')
->select('COUNT(s.id)')
->where('s.entityType = :type')
->andWhere('s.entityId = :id')
->andWhere('s.isTrial = true')
->setParameter('type', $entityType)
->setParameter('id', $entityId)
->getQuery()
->getSingleScalarResult();
return $count > 0;
}
public function save(ClinicSubscription $subscription): void
{
$this->getEntityManager()->persist($subscription);
$this->getEntityManager()->flush();
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Subscription\Repository;
use App\Subscription\Entity\SubscriptionPeriod;
use App\Subscription\Entity\SubscriptionPlan;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class SubscriptionPeriodRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, SubscriptionPeriod::class);
}
public function findByUuid(string $uuid): ?SubscriptionPeriod
{
return $this->findOneBy(['uuid' => $uuid]);
}
public function findTrialPeriodForPlan(SubscriptionPlan $plan): ?SubscriptionPeriod
{
return $this->findOneBy(['plan' => $plan, 'isTrial' => true, 'active' => true]);
}
public function save(SubscriptionPeriod $period): void
{
$this->getEntityManager()->persist($period);
$this->getEntityManager()->flush();
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Subscription\Repository;
use App\Subscription\Entity\SubscriptionPlan;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class SubscriptionPlanRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, SubscriptionPlan::class);
}
public function findByUuid(string $uuid): ?SubscriptionPlan
{
return $this->findOneBy(['uuid' => $uuid]);
}
public function findByName(string $name): ?SubscriptionPlan
{
return $this->findOneBy(['name' => $name, 'active' => true]);
}
public function findAllActive(): array
{
return $this->createQueryBuilder('p')
->where('p.active = true')
->orderBy('p.level', 'ASC')
->getQuery()
->getResult();
}
public function save(SubscriptionPlan $plan): void
{
$this->getEntityManager()->persist($plan);
$this->getEntityManager()->flush();
}
}