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
@@ -4,11 +4,13 @@ namespace App\Secretary\Controller;
use App\Auth\Entity\User;
use App\Auth\Repository\UserRepository;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Repository\DoctorRepository;
use App\Secretary\Entity\DoctorSecretary;
use App\Secretary\Repository\DoctorSecretaryRepository;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
use App\Subscription\Service\SubscriptionService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
@@ -19,14 +21,13 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class SecretaryController extends BaseController
{
// TODO: link to subscription plan (Task 15). Basic plan = 1, advanced = 3
private const MAX_SECRETARIES = 1;
public function __construct(
private readonly DoctorSecretaryRepository $secretaryRepo,
private readonly DoctorRepository $doctorRepo,
private readonly ClinicRepository $clinicRepo,
private readonly UserRepository $userRepo,
private readonly UserPasswordHasherInterface $hasher,
private readonly SubscriptionService $subscriptionService,
) {}
#[Route('/api/v1/secretary', methods: ['POST'])]
@@ -50,9 +51,12 @@ class SecretaryController extends BaseController
return $this->error(ErrorCodes::ERR_AUTH_006, 'دسترسی ممنوع', 403);
}
// Check plan limit
// Check plan limit (dynamic via SubscriptionService)
$entityType = 'doctor';
$entityId = $doctor->getId();
$limit = $this->subscriptionService->getSecretaryLimit($entityType, $entityId);
$activeCount = $this->secretaryRepo->countActiveByDoctor($doctor);
if ($activeCount >= self::MAX_SECRETARIES) {
if ($activeCount >= $limit) {
return $this->error(ErrorCodes::ERR_SECRETARY_001, ErrorCodes::message(ErrorCodes::ERR_SECRETARY_001), 422);
}