# Seed واقعی دیتا — پاک‌سازی و ایجاد ۱۰۰ دکتر به ازای هر شهر ## زمینه پروژه ClinicPro نیاز به دیتای واقعی و کامل برای تست و نمایش دارد. در حال حاضر دیتا ناقص یا تست‌نشده است. باید دیتابیس از دکتر، کلینیک، منشی و بیمار پاک شود، سپس دیتای واقعی با پروفایل کامل ایجاد شود. ## هدف ۱. پاک‌سازی کامل: users، doctors، clinics، patient_records، doctor_secretaries ۲. ایجاد یک **کلینیک نمونه کامل** با همه فیلدها ۳. ایجاد یک **دکتر نمونه کامل** با برنامه کاری و منشی ۴. ایجاد **۱۰۰ دکتر به ازای هر شهر** در تخصص‌های مختلف ## ساختار دیتابیس (جداول واقعی) ``` users → id, uuid, mobile_number, password_hash, real_name, roles JSON, status doctors → id, uuid, user_id, name, gender, medical_system_code, mobile_number, activity_time, degree, info, doctor_rate, doctor_rate_percentage, active_doctor_appointment, representation_id clinics → id, uuid, user_id, name, info, address, telephone, is_24_7, working_days, latitude, longitude, city_id, province_id, representation_id, is_active doctor_addresses → id, uuid, doctor_id, clinic_id, city_id, province_id, type('personal'|'clinic'), name, address, telephone weekly_schedules → id, uuid, doctor_id, setting (JSON — آرایه ۷ روز) doctor_specialties → doctor_id, specialty_id doctor_expertise → doctor_id, service_id doctor_insurances → doctor_id, insurance_id doctor_cities → doctor_id, city_id doctor_provinces → doctor_id, province_id clinic_doctors → clinic_id, doctor_id clinic_specialties → clinic_id, specialty_id clinic_services → clinic_id, service_id clinic_insurances → clinic_id, insurance_id doctor_secretaries → id, uuid, doctor_id, secretary_id, active, owner_type, clinic_id patient_records → id, uuid, user_id, entity_type, entity_id, created_by_type, created_by_id ``` ## IDهای واقعی lookup tables ### شهرها (cities.id) ``` 101=تبریز 102=ارومیه 103=اردبیل 104=اصفهان 105=کرج 106=ایلام 107=بوشهر 108=تهران 109=شهرکرد 110=بیرجند 111=مشهد 112=بجنورد 113=اهواز 114=زنجان 115=سمنان 116=زاهدان 117=شیراز 118=قزوین 119=قم 120=سنندج 121=کرمان 122=کرمانشاه 123=یاسوج 125=گرگان 126=رشت 127=خرم‌آباد 128=ساری 129=اراک 130=بندرعباس 131=همدان 132=یزد ``` ### استان‌ها (provinces.id) ``` 1=آذربایجان شرقی 2=آذربایجان غربی 3=اردبیل 4=اصفهان 5=البرز 6=ایلام 7=بوشهر 8=تهران 9=چهارمحال 10=خراسان جنوبی 11=خراسان رضوی 12=خراسان شمالی 13=خوزستان 14=زنجان 15=سمنان 16=سیستان 17=فارس 18=قزوین 19=قم 20=کردستان 21=کرمان 22=کرمانشاه 23=کهگیلویه 24=گلستان 25=گیلان 26=لرستان 27=مازندران 28=مرکزی 29=هرمزگان 30=همدان 100=یزد ``` نگاشت شهر → استان: `101→1, 102→2, 103→3, 104→4, 105→5, 106→6, 107→7, 108→8, 109→9, 110→10, 111→11, 112→12, 113→13, 114→14, 115→15, 116→16, 117→17, 118→18, 119→19, 120→20, 121→21, 122→22, 123→23, 125→24, 126→25, 127→26, 128→27, 129→28, 130→29, 131→30, 132→100` ### تخصص‌ها (specialties.id) — دسته‌بندی برای توزیع واقعی ``` داخلی: 1,2,3,4,5,6,7,8,9,10,11,12 جراحی: 20,21,22,23,24,25,26,27,28,29,30 اطفال: 40,41,42,43,44,45 زنان: 60,61,62,63,64,65 روانپزشکی: 70,71,72,73,74 پوست: 80,81,82,83,84 چشم: 90,91,92,93,94,95,96,97,98 ENT: 100,101,102,103,104 ارتوپدی: 110,111,112,113,114,115,116 اورولوژی: 120,121,122,123,124 رادیولوژی: 130,131,132,133,134 انکولوژی: 150,151,152 طب فیزیکی: 170,171,172,173 دندانپزشکی: 180,181,182,183,184,185,186,187,188,189 اورژانس/عمومی: 190,200 ``` ### خدمات پزشکی (doctor_services.id) — نمونه‌هایی برای هر تخصص ``` قلب: 101,102,103,104,105,110 گوارش: 201,202,203,210 ریه: 301,302,303,307 کلیه: 401,402,403,406 غدد: 501,502,503,505,506 روماتولوژی: 601,602,603,604 خون: 701,702,703,704 نورولوژی: 801,802,803,804,805 آلرژی: 901,902,903,905 عفونی: 1001,1002,1003 جراحی عمومی: 2101,2102,2103,2104,2105,2113 جراحی مغز: 2201,2202,2203,2207 ``` ### بیمه‌ها (insurances.id) ``` 1=تأمین اجتماعی 2=خدمات درمانی 3=نیروهای مسلح 4=کمیته امداد 5=بهزیستی 6=بیمه روستایی 7=ایران 8=آسیا 9=البرز 10=پارسیان 11=سامان 12=میهن 13=دانا 14=رازی 15=کوثر ``` ## ساختار weekly_schedules.setting (JSON) آرایه ۷ عنصر (شنبه تا جمعه). هر عنصر: ```json { "sessions": [ { "active": true, "location_id": , "start_time": "09:00", "end_time": "13:00", "duration_per_patient": 20, "has_rest": true, "rest_interval": 60, "time_to_rest": 10, "patient_limit": null } ] } ``` روزهای بدون کار: `{"sessions": []}` ## وظایف ### ۱. ایجاد فایل seed_realistic_data.php فایل را در ریشه پروژه (`/var/www/html/seed_realistic_data.php`) بساز. این فایل باید: #### بخش A — پاک‌سازی (به ترتیب FK) ```php // حذف به ترتیب وابستگی FK $conn->executeStatement('SET FOREIGN_KEY_CHECKS=0'); $conn->executeStatement('DELETE FROM weekly_schedules WHERE doctor_id IN (SELECT id FROM doctors)'); $conn->executeStatement('DELETE FROM doctor_addresses'); $conn->executeStatement('DELETE FROM doctor_specialties'); $conn->executeStatement('DELETE FROM doctor_expertise'); $conn->executeStatement('DELETE FROM doctor_insurances'); $conn->executeStatement('DELETE FROM doctor_cities'); $conn->executeStatement('DELETE FROM doctor_provinces'); $conn->executeStatement('DELETE FROM doctor_secretaries'); $conn->executeStatement('DELETE FROM clinic_doctors'); $conn->executeStatement('DELETE FROM clinic_specialties'); $conn->executeStatement('DELETE FROM clinic_services'); $conn->executeStatement('DELETE FROM clinic_insurances'); $conn->executeStatement('DELETE FROM patient_records'); $conn->executeStatement('DELETE FROM appointments'); $conn->executeStatement('DELETE FROM payments'); // حذف doctors, clinics, users (به جز ادمین‌ها) $conn->executeStatement("DELETE d FROM doctors d"); $conn->executeStatement("DELETE c FROM clinics c"); $conn->executeStatement("DELETE u FROM users u WHERE JSON_CONTAINS(u.roles, '\"ROLE_DOCTOR\"') OR JSON_CONTAINS(u.roles, '\"ROLE_CLINIC\"') OR JSON_CONTAINS(u.roles, '\"ROLE_PATIENT\"') OR JSON_CONTAINS(u.roles, '\"ROLE_SECRETARY\"')"); $conn->executeStatement('SET FOREIGN_KEY_CHECKS=1'); ``` #### بخش B — کلینیک نمونه کامل (تبریز) یک کلینیک با همه فیلدها: - نام: کلینیک تخصصی امید تبریز - city_id=101, province_id=1 - representation_id=101 (تبریز) - تمام specialties داخلی + قلب - بیمه‌های 1,2,3,7,8,9 - خدمات 201,202,203,101,102,103 #### بخش C — دکتر نمونه کامل (تبریز) دکتر کامل با: - تخصص قلب (id=3) + داخلی (id=2) - بیمه‌های 1,2,3,7 - خدمات 101,102,103,104,110 - آدرس مطب در تبریز + آدرس کلینیک امید - برنامه کاری: شنبه تا چهارشنبه ۹-۱۳ و ۱۴-۱۸، پنجشنبه ۹-۱۳، جمعه تعطیل - یک منشی - representation_id=101 #### بخش D — ۱۰۰ دکتر برای هر شهر (bulk generation) برای شهرهای: `[101,102,103,104,105,108,111,113,117,121,122,126,128,131,132]` (۱۵ شهر مهم) هر دکتر باید داشته باشد: - user با موبایل منحصربه‌فرد (فرمت: `09XXXXXXXXX` — از ۰۹۱۰۰۱۰۰۰۰۰ به بالا) - نام واقعی فارسی (از لیست ۱۰۰ نام ایرانی) - پروفایل کامل: gender, degree, medical_system_code, info, rate - تخصص (توزیع واقعی بین تخصص‌ها) - ۲-۳ خدمات متناسب با تخصص - بیمه‌های 1,2 (پایه) + یک بیمه تکمیلی تصادفی - یک آدرس مطب در شهرش - برنامه کاری (۵ روز کاری) - representation_id برابر با id شهر **لیست نام‌های واقعی ایرانی (برای استفاده در generator):** ```php $firstNames = ['علی', 'محمد', 'حسین', 'رضا', 'امیر', 'مهدی', 'سعید', 'احمد', 'حسن', 'جواد', 'فاطمه', 'زهرا', 'مریم', 'سارا', 'نگین', 'الهه', 'نیلوفر', 'شیما', 'لیلا', 'نازنین', 'کریم', 'ابراهیم', 'اکبر', 'ناصر', 'پیمان', 'بهروز', 'شاهین', 'کاوه', 'آرش', 'سهراب', 'مینا', 'آزاده', 'ندا', 'رویا', 'پریسا', 'گلناز', 'سپیده', 'بهاره', 'شادی', 'فریده']; $lastNames = ['رضایی', 'محمدی', 'حسینی', 'علوی', 'موسوی', 'احمدی', 'کریمی', 'صادقی', 'جعفری', 'مرادی', 'نجفی', 'تبریزی', 'اصفهانی', 'مشهدی', 'شیرازی', 'کرمانی', 'رشیدی', 'نظری', 'ابراهیمی', 'قاسمی', 'یوسفی', 'منصوری', 'زارعی', 'ملکی', 'بهرامی', 'سلیمانی', 'نوری']; ``` **توزیع واقعی تخصص‌ها در ۱۰۰ دکتر:** ```php $specialtyGroups = [ ['specs' => [200], 'services' => [], 'degree' => 'general', 'count' => 15], // عمومی ۱۵ ['specs' => [2,3], 'services' => [101,102,103,110], 'degree' => 'specialist', 'count' => 10], // داخلی+قلب ۱۰ ['specs' => [4], 'services' => [201,202,203,210], 'degree' => 'specialist', 'count' => 6], // گوارش ۶ ['specs' => [10], 'services' => [801,802,803,805], 'degree' => 'specialist', 'count' => 6], // نورولوژی ۶ ['specs' => [21], 'services' => [2101,2102,2103,2113], 'degree' => 'specialist', 'count' => 8],// جراحی ۸ ['specs' => [61], 'services' => [], 'degree' => 'specialist', 'count' => 8], // زنان ۸ ['specs' => [41], 'services' => [], 'degree' => 'specialist', 'count' => 8], // اطفال ۸ ['specs' => [111], 'services' => [], 'degree' => 'specialist', 'count' => 7], // ارتوپدی ۷ ['specs' => [81,82], 'services' => [], 'degree' => 'specialist', 'count' => 6], // پوست ۶ ['specs' => [91], 'services' => [], 'degree' => 'specialist', 'count' => 6], // چشم ۶ ['specs' => [101], 'services' => [], 'degree' => 'specialist', 'count' => 5], // ENT ۵ ['specs' => [71], 'services' => [], 'degree' => 'specialist', 'count' => 5], // روانپزشکی ۵ ['specs' => [121], 'services' => [], 'degree' => 'specialist', 'count' => 4], // اورولوژی ۴ ['specs' => [181], 'services' => [], 'degree' => 'dentist', 'count' => 6], // دندانپزشکی ۶ ]; // جمع = 100 ``` **فرمت برنامه کاری (۷ روز شنبه تا جمعه):** ```php function makeSchedule(int $addressId): string { $days = []; for ($i = 0; $i < 7; $i++) { if ($i === 6) { // جمعه تعطیل $days[] = ['sessions' => []]; } elseif ($i === 5) { // پنجشنبه نیمه‌وقت $days[] = ['sessions' => [ ['active' => true, 'location_id' => $addressId, 'start_time' => '09:00', 'end_time' => '13:00', 'duration_per_patient' => 20, 'has_rest' => false, 'rest_interval' => 60, 'time_to_rest' => 10, 'patient_limit' => null] ]]; } else { // شنبه تا چهارشنبه $days[] = ['sessions' => [ ['active' => true, 'location_id' => $addressId, 'start_time' => '09:00', 'end_time' => '13:00', 'duration_per_patient' => 20, 'has_rest' => true, 'rest_interval' => 60, 'time_to_rest' => 10, 'patient_limit' => null], ['active' => true, 'location_id' => $addressId, 'start_time' => '14:00', 'end_time' => '18:00', 'duration_per_patient' => 20, 'has_rest' => false, 'rest_interval' => 60, 'time_to_rest' => 10, 'patient_limit' => null], ]]; } } return json_encode($days, JSON_UNESCAPED_UNICODE); } ``` ## نکات مهم اجرا - **نام فایل PHP:** `seed_realistic_data.php` در ریشه پروژه - **password_hash:** از `password_hash('Test@1234', PASSWORD_BCRYPT)` برای همه کاربران - **roles JSON:** `'["ROLE_USER","ROLE_DOCTOR"]'` برای دکتر، `'["ROLE_USER","ROLE_CLINIC"]'` برای کلینیک - **uuid:** از `Symfony\Component\Uid\Uuid::v4()->toRfc4122()` یا `bin2hex(random_bytes(8))` — باید unique باشد - **موبایل منحصربه‌فرد:** از counter شمارنده استفاده کن تا تکراری نشود - **representation_id:** برابر با city_id شهر مربوطه (چون cities.id = representations.id) - **FK ها:** weekly_schedule بعد از ایجاد doctor_address insert شود (نیاز به address.id دارد) - **transaction:** همه insert ها در یک transaction بزرگ بپیچ تا در صورت خطا rollback شود - **echo پیشرفت:** بعد از هر شهر تعداد دکتر ایجادشده را چاپ کن ## دستور اجرا ```bash ddev exec php seed_realistic_data.php ``` ## خروجی مورد انتظار ``` ✅ پاک‌سازی کامل شد ✅ کلینیک امید تبریز ایجاد شد (id: X) ✅ دکتر نمونه تبریز ایجاد شد (id: Y) 🏙️ تبریز: 100 دکتر ایجاد شد 🏙️ تهران: 100 دکتر ایجاد شد ... ✅ پایان — مجموع X دکتر در Y شهر ایجاد شد ```