Implement SMS panel user flow and patient records system; add wallet charging, automatic reminders, and patient session management with detailed database schema and user flows.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# معماری — تسک ۱۳: سرویسهای کلینیک
|
||||
|
||||
## ساختار فایلها
|
||||
|
||||
```
|
||||
src/ClinicService/
|
||||
├── Controller/
|
||||
│ └── ClinicServiceController.php
|
||||
├── Entity/
|
||||
│ ├── ServiceSection.php
|
||||
│ └── ServiceItem.php
|
||||
└── Repository/
|
||||
├── ServiceSectionRepository.php
|
||||
└── ServiceItemRepository.php
|
||||
```
|
||||
|
||||
## Entity: ServiceSection
|
||||
|
||||
```php
|
||||
#[ORM\Entity(repositoryClass: ServiceSectionRepository::class)]
|
||||
#[ORM\Table(name: 'service_sections')]
|
||||
#[ORM\Index(columns: ['entity_type', 'entity_id'], name: 'idx_service_sections_entity')]
|
||||
class ServiceSection
|
||||
{
|
||||
#[ORM\Id, ORM\GeneratedValue, ORM\Column(type: 'integer')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 36, unique: true)]
|
||||
private string $uuid;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 10)]
|
||||
private string $entityType; // 'doctor' | 'clinic'
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $entityId;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 200)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $active = true;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $updatedAt;
|
||||
}
|
||||
```
|
||||
|
||||
## Entity: ServiceItem
|
||||
|
||||
```php
|
||||
#[ORM\Entity(repositoryClass: ServiceItemRepository::class)]
|
||||
#[ORM\Table(name: 'service_items')]
|
||||
class ServiceItem
|
||||
{
|
||||
#[ORM\Id, ORM\GeneratedValue, ORM\Column(type: 'integer')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 36, unique: true)]
|
||||
private string $uuid;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ServiceSection::class)]
|
||||
#[ORM\JoinColumn(name: 'section_id', nullable: false, onDelete: 'CASCADE')]
|
||||
private ServiceSection $section;
|
||||
|
||||
// staff nullable — پرسنل انجامدهنده
|
||||
#[ORM\ManyToOne(targetEntity: \App\Staff\Entity\ClinicStaff::class)]
|
||||
#[ORM\JoinColumn(name: 'staff_id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?\App\Staff\Entity\ClinicStaff $staff = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 200)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $priceRials = 0;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $active = true;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $updatedAt;
|
||||
}
|
||||
```
|
||||
|
||||
## Controller: ClinicServiceController
|
||||
|
||||
```php
|
||||
#[Route('/api/v1')]
|
||||
class ClinicServiceController extends BaseController
|
||||
{
|
||||
// برای همه write actions → gate check اول:
|
||||
private function assertServicesFeature(): void
|
||||
{
|
||||
[$entityType, $entityId] = $this->resolveEntityContext();
|
||||
if (!$this->subscriptionService->hasFeature($entityType, $entityId, 'services')) {
|
||||
throw new AppException(ErrorCodes::ERR_SUBSCRIPTION_REQUIRED, null, 403);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/service-sections', methods: ['GET'])]
|
||||
public function listSections(): JsonResponse { ... }
|
||||
|
||||
#[Route('/service-section', methods: ['POST'])]
|
||||
public function createSection(Request $request): JsonResponse
|
||||
{
|
||||
$this->assertServicesFeature();
|
||||
// ...
|
||||
}
|
||||
|
||||
// سایر endpoint ها ...
|
||||
}
|
||||
```
|
||||
|
||||
## نکته DELETE سرویس با استفاده در پرونده
|
||||
|
||||
```php
|
||||
// اگر session_services.service_item_id → این item باشد:
|
||||
// FK ON DELETE RESTRICT → Doctrine exception → catch و return 409
|
||||
try {
|
||||
$this->em->remove($item);
|
||||
$this->em->flush();
|
||||
} catch (\Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException $e) {
|
||||
return $this->error(ErrorCodes::ERR_SERVICE_ITEM_IN_USE, 'این سرویس در پرونده بیمار استفاده شده است', 409);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user