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,172 @@
|
||||
# معماری — تسک ۱۰: مدیریت پرسنل (Staff)
|
||||
|
||||
## ساختار فایلها
|
||||
|
||||
```
|
||||
src/Staff/
|
||||
├── Controller/
|
||||
│ └── StaffController.php
|
||||
├── Entity/
|
||||
│ └── ClinicStaff.php
|
||||
├── Repository/
|
||||
│ └── ClinicStaffRepository.php
|
||||
└── Service/
|
||||
└── StaffService.php
|
||||
```
|
||||
|
||||
## Entity: ClinicStaff
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Staff\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[ORM\Entity(repositoryClass: \App\Staff\Repository\ClinicStaffRepository::class)]
|
||||
#[ORM\Table(name: 'clinic_staff')]
|
||||
#[ORM\Index(columns: ['entity_type', 'entity_id', 'active'], name: 'idx_clinic_staff_entity')]
|
||||
class ClinicStaff
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 36, unique: true)]
|
||||
private string $uuid;
|
||||
|
||||
// polymorphic — 'doctor' یا 'clinic'
|
||||
#[ORM\Column(type: 'string', length: 10)]
|
||||
private string $entityType;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $entityId;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 200)]
|
||||
private string $fullName;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 20, nullable: true)]
|
||||
private ?string $phone = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 100, nullable: true)]
|
||||
private ?string $jobTitle = null;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $address = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 10, nullable: true)]
|
||||
private ?string $nationalCode = null;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $active = true;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private int $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->uuid = (string) Uuid::v4();
|
||||
$this->createdAt = time();
|
||||
$this->updatedAt = time();
|
||||
}
|
||||
|
||||
// getters/setters ...
|
||||
}
|
||||
```
|
||||
|
||||
## Controller: StaffController
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Staff\Controller;
|
||||
|
||||
use App\Shared\Controller\BaseController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/v1')]
|
||||
class StaffController extends BaseController
|
||||
{
|
||||
#[Route('/staff', methods: ['GET'])]
|
||||
public function list(): JsonResponse
|
||||
{
|
||||
// 1. از JWT: entity_type و entity_id (db_key + db_uuid) را بگیر
|
||||
// 2. StaffRepository::findByEntity($entityType, $entityId) صدا بزن
|
||||
// 3. return $this->success($items);
|
||||
}
|
||||
|
||||
#[Route('/staff', methods: ['POST'])]
|
||||
public function create(Request $request): JsonResponse
|
||||
{
|
||||
// 1. validate: full_name اجباری
|
||||
// 2. ClinicStaff جدید با entityType/entityId از JWT بساز
|
||||
// 3. persist و flush
|
||||
// 4. return $this->success($staff->toArray());
|
||||
}
|
||||
|
||||
#[Route('/staff/{uuid}', methods: ['PATCH'])]
|
||||
public function update(string $uuid, Request $request): JsonResponse
|
||||
{
|
||||
// 1. find by uuid → 404 اگر نبود
|
||||
// 2. بررسی مالکیت: staff->entityType/entityId == JWT claim → 403 اگر نبود
|
||||
// 3. ویرایش فیلدهای موجود در body
|
||||
// 4. return $this->success($staff->toArray());
|
||||
}
|
||||
|
||||
#[Route('/staff/{uuid}/toggle', methods: ['PATCH'])]
|
||||
public function toggle(string $uuid): JsonResponse
|
||||
{
|
||||
// 1. find → ownership check
|
||||
// 2. active = !active
|
||||
// 3. return $this->success(['active' => $staff->isActive()]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Service: StaffService
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Staff\Service;
|
||||
|
||||
class StaffService
|
||||
{
|
||||
public function toArray(ClinicStaff $staff): array
|
||||
{
|
||||
return [
|
||||
'uuid' => $staff->getUuid(),
|
||||
'full_name' => $staff->getFullName(),
|
||||
'phone' => $staff->getPhone(),
|
||||
'job_title' => $staff->getJobTitle(),
|
||||
'address' => $staff->getAddress(),
|
||||
'national_code' => $staff->getNationalCode(),
|
||||
'active' => $staff->isActive(),
|
||||
'created_at' => $staff->getCreatedAt(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## نحوه خواندن entity_type / entity_id از JWT
|
||||
|
||||
```php
|
||||
// در BaseController یا trait:
|
||||
// JWT payload شامل: db_key ('doctor'/'clinic') و db_uuid (uuid entity)
|
||||
// باید uuid را به id تبدیل کنیم:
|
||||
$entityType = $this->getUser()->getDbKey(); // 'doctor' یا 'clinic'
|
||||
$entityUuid = $this->getUser()->getDbUuid();
|
||||
// سپس از Repository مربوطه id واقعی را بگیریم
|
||||
```
|
||||
|
||||
## وابستگیهای آینده
|
||||
|
||||
- `src/ClinicService/Entity/ServiceItem.php` → `staff_id FK → clinic_staff.id`
|
||||
- `src/Patient/Entity/SessionService.php` → `staff_id FK → clinic_staff.id`
|
||||
Reference in New Issue
Block a user