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:
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace App\Patient\Service;
|
||||
|
||||
use App\Appointment\Entity\Appointment;
|
||||
use App\Auth\Repository\UserRepository;
|
||||
use App\ClinicService\Repository\ServiceItemRepository;
|
||||
use App\Patient\Entity\PatientRecord;
|
||||
use App\Patient\Entity\PatientSession;
|
||||
use App\Patient\Entity\SessionService;
|
||||
use App\Patient\Repository\PatientRecordRepository;
|
||||
use App\Patient\Repository\PatientSessionRepository;
|
||||
use App\Patient\Repository\SessionServiceRepository;
|
||||
use App\Staff\Repository\ClinicStaffRepository;
|
||||
use App\Subscription\Service\SubscriptionService;
|
||||
|
||||
class PatientService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PatientRecordRepository $recordRepo,
|
||||
private readonly PatientSessionRepository $sessionRepo,
|
||||
private readonly SessionServiceRepository $sessionServiceRepo,
|
||||
private readonly ServiceItemRepository $serviceItemRepo,
|
||||
private readonly ClinicStaffRepository $staffRepo,
|
||||
private readonly UserRepository $userRepo,
|
||||
private readonly SubscriptionService $subscriptionService,
|
||||
) {}
|
||||
|
||||
public function calculateFinalPrice(int $visitPrice, float $baseDiscount, float $suppDiscount, array $serviceItems): array
|
||||
{
|
||||
$afterBase = $visitPrice * (1 - $baseDiscount / 100);
|
||||
$afterSupp = $afterBase * (1 - $suppDiscount / 100);
|
||||
$servicesTotal = array_sum(array_column($serviceItems, 'price_rials'));
|
||||
|
||||
return [
|
||||
'services_total_rials' => (int) $servicesTotal,
|
||||
'final_price_rials' => (int) round($afterSupp) + (int) $servicesTotal,
|
||||
];
|
||||
}
|
||||
|
||||
public function autoCreateOnAppointmentConfirm(Appointment $appointment): void
|
||||
{
|
||||
$doctor = $appointment->getDoctor();
|
||||
$entityType = 'doctor';
|
||||
$entityId = $doctor->getId();
|
||||
|
||||
if (!$this->subscriptionService->hasFeature($entityType, $entityId, 'patient_records')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$patient = $appointment->getUser();
|
||||
|
||||
$record = $this->recordRepo->findByEntityAndUser($entityType, $entityId, $patient);
|
||||
if ($record === null) {
|
||||
$record = new PatientRecord($entityType, $entityId, $patient, 'system', $doctor->getId());
|
||||
$this->recordRepo->save($record);
|
||||
}
|
||||
|
||||
$session = new PatientSession($record, $appointment);
|
||||
$this->sessionRepo->save($session);
|
||||
}
|
||||
|
||||
public function createSession(
|
||||
PatientRecord $record,
|
||||
array $data,
|
||||
string $entityType,
|
||||
int $entityId
|
||||
): PatientSession {
|
||||
$session = new PatientSession($record);
|
||||
|
||||
if (!empty($data['appointment_uuid'])) {
|
||||
// appointment را از بیرون resolve میکنند و session را ست میکنند
|
||||
}
|
||||
|
||||
$session->setInsuranceBaseId(isset($data['insurance_base_id']) ? (int) $data['insurance_base_id'] : null);
|
||||
$session->setInsuranceSupplementaryId(isset($data['insurance_supplementary_id']) ? (int) $data['insurance_supplementary_id'] : null);
|
||||
$session->setVisitPriceRials((int) ($data['visit_price_rials'] ?? 0));
|
||||
$session->setBaseInsuranceDiscountPercent((float) ($data['base_insurance_discount_percent'] ?? 0));
|
||||
$session->setSupplementaryDiscountPercent((float) ($data['supplementary_discount_percent'] ?? 0));
|
||||
$session->setPaymentMethod($data['payment_method'] ?? 'pending');
|
||||
$session->setNotes($data['notes'] ?? null);
|
||||
|
||||
// جمعآوری service items
|
||||
$serviceItemsData = [];
|
||||
foreach (($data['services'] ?? []) as $svc) {
|
||||
$item = $this->serviceItemRepo->findByUuid($svc['service_item_uuid'] ?? '');
|
||||
if ($item !== null) {
|
||||
$serviceItemsData[] = ['price_rials' => $item->getPriceRials()];
|
||||
}
|
||||
}
|
||||
|
||||
$priceCalc = $this->calculateFinalPrice(
|
||||
$session->getVisitPriceRials(),
|
||||
$session->getBaseInsuranceDiscountPercent(),
|
||||
$session->getSupplementaryDiscountPercent(),
|
||||
$serviceItemsData
|
||||
);
|
||||
|
||||
$session->setServicesTotalRials($priceCalc['services_total_rials']);
|
||||
$session->setFinalPriceRials($priceCalc['final_price_rials']);
|
||||
|
||||
$this->sessionRepo->save($session);
|
||||
|
||||
// ثبت session services
|
||||
foreach (($data['services'] ?? []) as $svc) {
|
||||
$item = $this->serviceItemRepo->findByUuid($svc['service_item_uuid'] ?? '');
|
||||
if ($item === null) {
|
||||
continue;
|
||||
}
|
||||
$staff = !empty($svc['staff_uuid']) ? $this->staffRepo->findByUuid($svc['staff_uuid']) : null;
|
||||
$ss = new SessionService($session, $item, $staff);
|
||||
$this->sessionServiceRepo->save($ss);
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user