Files
hamed de1a78a235 feat: Implement SMS sending functionality with KavehNegar and Rangineh providers
- Add SendSmsMessage class for encapsulating SMS message data.
- Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS.
- Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates.
- Develop SendSmsHandler for handling SMS sending messages.
- Create SmsService to manage SMS dispatching and logging.
- Add UserProfileController for managing user profiles with CRUD operations.
- Implement UserProfile entity and repository for user profile data management.
- Update symfony.lock and bootstrap.php for project dependencies and environment setup.
2026-06-09 22:00:34 +03:30

6.5 KiB
Raw Permalink Blame History

معماری — تسک ۰۵: ماژول دکتر

ساختار فایل‌ها

src/Module/Doctor/
├── Controller/
│   ├── DoctorController.php         ← CRUD دکتر + لیست + جستجو
│   ├── DoctorImageController.php    ← آپلود تصویر
│   └── DoctorAddressController.php  ← CRUD آدرس مطب
├── Service/
│   ├── DoctorService.php
│   └── DoctorAddressService.php
├── Repository/
│   ├── DoctorRepository.php
│   └── DoctorAddressRepository.php
├── Entity/
│   ├── Doctor.php
│   └── DoctorAddress.php
├── DTO/
│   ├── Request/
│   │   ├── CreateDoctorRequest.php
│   │   ├── UpdateDoctorRequest.php
│   │   ├── DoctorFilterRequest.php
│   │   ├── CreateDoctorAddressRequest.php
│   │   └── UpdateDoctorAddressRequest.php
│   └── Response/
│       ├── DoctorResponse.php        ← view کامل با آمار
│       ├── DoctorListItemResponse.php ← لیست/جستجو
│       └── DoctorAddressResponse.php
└── Voter/
    └── DoctorVoter.php

Entity: Doctor (بر اساس فیلدهای واقعی Drupal)

#[ORM\Entity]
#[ORM\Table(name: 'doctors')]
class Doctor
{
    #[ORM\Id, ORM\GeneratedValue, ORM\Column]
    private int $id;

    #[ORM\Column(type: UuidType::NAME, unique: true)]
    private Uuid $uuid;

    #[ORM\OneToOne(targetEntity: User::class)]
    #[ORM\JoinColumn(nullable: false)]
    private User $user;                     // uid در Drupal

    #[ORM\Column(length: 100)]
    private string $name;                   // field_name

    #[ORM\Column(length: 10, nullable: true)]
    private ?string $gender;                // field_gender

    #[ORM\Column(length: 50)]
    private string $medicalSystemCode;      // field_doctor_id (شماره نظام پزشکی)

    #[ORM\Column(type: 'integer', nullable: true)]
    private ?int $activityTime;             // field_activity_time (timestamp سال شروع)

    #[ORM\Column(length: 100, nullable: true)]
    private ?string $degree;                // field_degree

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $info;                  // field_info

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $imagePath;             // field_image (media)

    #[ORM\Column(type: 'decimal', precision: 3, scale: 1, options: ['default' => 3.5])]
    private float $doctorRate = 3.5;        // field_doctor_rate

    #[ORM\Column(type: 'decimal', precision: 5, scale: 1, options: ['default' => 60])]
    private float $doctorRatePercentage = 60; // field_doctor_rate_percentage

    #[ORM\Column(type: 'boolean', options: ['default' => true])]
    private bool $activeDoctorAppointment = true; // field_active_doctor_appointmen

    #[ORM\ManyToOne(targetEntity: Representation::class)]
    #[ORM\JoinColumn(nullable: true)]
    private ?Representation $representation; // field_representation (multi-tenant)

    // ManyToMany relations (field_specialty, field_doctor_services, field_state, field_city)
    #[ORM\ManyToMany(targetEntity: Category::class)]
    #[ORM\JoinTable(name: 'doctor_specialties')]
    private Collection $specialties;        // field_specialty (چند مقداری)

    #[ORM\ManyToMany(targetEntity: Category::class)]
    #[ORM\JoinTable(name: 'doctor_services')]
    private Collection $services;           // field_doctor_services (چند مقداری)

    #[ORM\ManyToMany(targetEntity: Category::class)]
    #[ORM\JoinTable(name: 'doctor_states')]
    private Collection $states;             // field_state

    #[ORM\ManyToMany(targetEntity: Category::class)]
    #[ORM\JoinTable(name: 'doctor_cities')]
    private Collection $cities;             // field_city

    #[ORM\OneToMany(targetEntity: DoctorAddress::class, mappedBy: 'doctor')]
    private Collection $addresses;

    // TimestampableTrait
}

Entity: DoctorAddress (بر اساس فیلدهای واقعی Drupal)

#[ORM\Entity]
#[ORM\Table(name: 'doctor_addresses')]
class DoctorAddress
{
    #[ORM\Id, ORM\GeneratedValue, ORM\Column]
    private int $id;

    #[ORM\Column(type: UuidType::NAME, unique: true)]
    private Uuid $uuid;

    #[ORM\ManyToOne(targetEntity: Doctor::class, inversedBy: 'addresses')]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    private Doctor $doctor;                 // field_doctor

    #[ORM\Column(length: 100, nullable: true)]
    private ?string $name;                  // field_name (نام مطب/شعبه)

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $address;               // field_address

    #[ORM\Column(length: 20, nullable: true)]
    private ?string $telephone;             // field_telephone (نه phone!)

    #[ORM\Column(type: 'decimal', precision: 10, scale: 8, nullable: true)]
    private ?float $latitude;               // field_latitude

    #[ORM\Column(type: 'decimal', precision: 11, scale: 8, nullable: true)]
    private ?float $longitude;              // field_longitude

    // TimestampableTrait
}

Response کامل دکتر (finalizeData)

{
  "id": 5, "uuid": "...",
  "name": "دکتر محمدی",
  "gender": "male",
  "experience": 12,
  "activity_time": 1388534400,
  "medical_system_code": "12345",
  "detail": "متخصص قلب و عروق...",
  "degree": "دکترای تخصصی",
  "specialties": [{"id": 3, "uuid": "...", "name": "قلب و عروق"}],
  "img": ["https://..."],
  "expertise": [{"id": 10, "uuid": "...", "name": "اکوکاردیوگرافی"}],
  "satisfaction": 87.5,
  "point": 4.4,
  "free_turn": "اولین نوبت آزاد: دوشنبه ۱۲ اردیبهشت ساعت ۱۰:۳۰",
  "hours_of_work": ["شنبه", "یکشنبه", "دوشنبه"],
  "address": [...],
  "average_rate": {"average_stars": 4.3, "total_rates": 87},
  "state": [{"id": 2, "uuid": "...", "name": "فارس"}],
  "city": [{"id": 5, "uuid": "...", "name": "شیراز"}]
}

منطق create دکتر (از DoctorService.php)

۱. اگر doctor_mobile_number داده شد:

  • کاربر با این موبایل را پیدا کن
  • اگر نقش doctor ندارد → 403
  • اگر قبلاً profile دکتر دارد → 403
  • اگر کاربر وجود ندارد → کاربر جدید با نقش doctor بساز ۲. اگر doctor_mobile_number نداده شد → کاربر جاری استفاده شود ۳. اعتبارسنجی همه فیلدهای اجباری ۴. ایجاد entity