bootEnv(__DIR__ . '/.env'); $kernel = new App\Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); $kernel->boot(); $conn = $kernel->getContainer()->get('doctrine')->getManager()->getConnection(); $now = time(); $passwordHash = password_hash('Test@1234', PASSWORD_BCRYPT); $mobileCounter = 9100100000; // شروع از 09100100000 // ── Helpers ────────────────────────────────────────────────────────────────── function newUuid(): string { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); } function nextMobile(): string { global $mobileCounter; return '0' . $mobileCounter++; } function makeSchedule(int $addressId, bool $fullWeek = true): 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], ]]; } elseif ($fullWeek) { $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], ]]; } else { $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], ]]; } } return json_encode($days, JSON_UNESCAPED_UNICODE); } // نگاشت شهر → استان $cityProvince = [ 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, ]; $cityNames = [ 101 => 'تبریز', 102 => 'ارومیه', 103 => 'اردبیل', 104 => 'اصفهان', 105 => 'کرج', 108 => 'تهران', 111 => 'مشهد', 113 => 'اهواز', 117 => 'شیراز', 121 => 'کرمان', 122 => 'کرمانشاه', 126 => 'رشت', 128 => 'ساری', 131 => 'همدان', 132 => 'یزد', ]; // توزیع تخصص‌ها برای ۱۰۰ دکتر $specialtyGroups = [ ['specs' => [200], 'services' => [], 'degree' => 'general', 'gender_mix' => 'both', 'count' => 15], ['specs' => [2, 3], 'services' => [101,102,103,110], 'degree' => 'specialist', 'gender_mix' => 'male', 'count' => 10], ['specs' => [4], 'services' => [201,202,203,210], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 6], ['specs' => [10], 'services' => [801,802,803,805], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 6], ['specs' => [21], 'services' => [2101,2102,2103,2113],'degree' => 'specialist','gender_mix' => 'male', 'count' => 8], ['specs' => [61], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'female', 'count' => 8], ['specs' => [41], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 8], ['specs' => [111], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'male', 'count' => 7], ['specs' => [81, 82], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 6], ['specs' => [91], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 6], ['specs' => [101], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 5], ['specs' => [71], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'both', 'count' => 5], ['specs' => [121], 'services' => [], 'degree' => 'specialist', 'gender_mix' => 'male', 'count' => 4], ['specs' => [181], 'services' => [], 'degree' => 'dentist', 'gender_mix' => 'both', 'count' => 6], ]; $maleFirstNames = ['علی', 'محمد', 'حسین', 'رضا', 'امیر', 'مهدی', 'سعید', 'احمد', 'حسن', 'جواد', 'کریم', 'ابراهیم', 'اکبر', 'ناصر', 'پیمان', 'بهروز', 'شاهین', 'کاوه', 'آرش', 'سهراب', 'فرزاد', 'بهنام', 'وحید', 'مجید', 'عباس', 'صادق', 'داود', 'یوسف', 'منصور', 'اسماعیل']; $femaleFirstNames = ['فاطمه', 'زهرا', 'مریم', 'سارا', 'نگین', 'الهه', 'نیلوفر', 'شیما', 'لیلا', 'نازنین', 'مینا', 'آزاده', 'ندا', 'رویا', 'پریسا', 'گلناز', 'سپیده', 'بهاره', 'شادی', 'فریده', 'سمانه', 'مهتاب', 'شهرزاد', 'گیتا', 'آناهیتا', 'سیمین', 'منیژه', 'ناهید', 'پگاه', 'روشنک']; $lastNames = ['رضایی', 'محمدی', 'حسینی', 'علوی', 'موسوی', 'احمدی', 'کریمی', 'صادقی', 'جعفری', 'مرادی', 'نجفی', 'تبریزی', 'اصفهانی', 'مشهدی', 'شیرازی', 'کرمانی', 'رشیدی', 'نظری', 'ابراهیمی', 'قاسمی', 'یوسفی', 'منصوری', 'زارعی', 'ملکی', 'بهرامی', 'سلیمانی', 'نوری', 'پارسا', 'امینی', 'زاهدی']; $degreeLabels = ['general' => 'پزشک عمومی', 'specialist' => 'متخصص', 'dentist' => 'دندانپزشک', 'subspecialist' => 'فوق‌تخصص']; $specNames = [ 2 => 'داخلی', 3 => 'قلب و عروق', 4 => 'گوارش', 10 => 'نورولوژی', 21 => 'جراحی عمومی', 41 => 'اطفال', 61 => 'زنان و زایمان', 71 => 'روانپزشکی', 81 => 'پوست', 82 => 'زیبایی پوست', 91 => 'چشم‌پزشکی', 101 => 'گوش، حلق و بینی', 111 => 'ارتوپدی', 121 => 'اورولوژی', 181 => 'دندانپزشکی', 200 => 'پزشکی عمومی', ]; $supplementaryInsurances = [7, 8, 9, 10, 11, 12, 13, 14, 15]; // ───────────────────────────────────────────────────────────────────────────── // بخش A — پاک‌سازی // ───────────────────────────────────────────────────────────────────────────── echo "🧹 پاک‌سازی دیتابیس...\n"; $conn->executeStatement('SET FOREIGN_KEY_CHECKS=0'); $conn->executeStatement('DELETE FROM weekly_schedules'); $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'); $conn->executeStatement('DELETE FROM sms_logs'); $conn->executeStatement('DELETE FROM rates'); $conn->executeStatement('DELETE FROM doctors'); $conn->executeStatement('DELETE FROM clinics'); $conn->executeStatement("DELETE FROM users WHERE JSON_CONTAINS(roles, '\"ROLE_DOCTOR\"') OR JSON_CONTAINS(roles, '\"ROLE_CLINIC\"') OR JSON_CONTAINS(roles, '\"ROLE_PATIENT\"') OR JSON_CONTAINS(roles, '\"ROLE_SECRETARY\"')"); $conn->executeStatement('SET FOREIGN_KEY_CHECKS=1'); echo "✅ پاک‌سازی کامل شد\n\n"; // ───────────────────────────────────────────────────────────────────────────── // بخش B — کلینیک نمونه کامل (تبریز) // ───────────────────────────────────────────────────────────────────────────── echo "🏥 ایجاد کلینیک نمونه...\n"; $clinicMobile = nextMobile(); $clinicUserUuid = newUuid(); $conn->executeStatement( 'INSERT INTO users (uuid, mobile_number, password_hash, real_name, roles, status, created_at, updated_at) VALUES (?,?,?,?,?,1,?,?)', [$clinicUserUuid, $clinicMobile, $passwordHash, 'کلینیک تخصصی امید', '["ROLE_USER","ROLE_CLINIC"]', $now, $now] ); $clinicUserId = (int) $conn->lastInsertId(); $clinicUuid = newUuid(); $conn->executeStatement( 'INSERT INTO clinics (uuid, user_id, name, info, address, telephone, is_24_7, working_days, latitude, longitude, city_id, province_id, representation_id, is_active, created_at, updated_at) VALUES (?,?,?,?,?,?,0,?,?,?,?,?,?,1,?,?)', [ $clinicUuid, $clinicUserId, 'کلینیک تخصصی امید تبریز', 'کلینیک تخصصی امید تبریز با بیش از ۲۰ سال سابقه در ارائه خدمات درمانی تخصصی. مجهز به پیشرفته‌ترین تجهیزات پزشکی و دارای تیمی از متخصصان برجسته در رشته‌های مختلف. پذیرش بیماران با بیمه‌های تامین اجتماعی، خدمات درمانی و بیمه‌های تکمیلی.', 'تبریز، خیابان ارتش، نبش کوچه سوم، ساختمان امید، طبقه اول', '04133445566', 'شنبه تا چهارشنبه ۸ تا ۲۰، پنجشنبه ۸ تا ۱۴', 37.0833, 35.7167, 101, 1, 101, // city, province, representation $now, $now, ] ); $clinicId = (int) $conn->lastInsertId(); // تخصص‌های کلینیک foreach ([1, 2, 3, 4, 10, 40, 60, 80, 90, 100, 110] as $specId) { $conn->executeStatement('INSERT IGNORE INTO clinic_specialties (clinic_id, specialty_id) VALUES (?,?)', [$clinicId, $specId]); } // بیمه‌های کلینیک foreach ([1, 2, 3, 7, 8, 9] as $insId) { $conn->executeStatement('INSERT IGNORE INTO clinic_insurances (clinic_id, insurance_id) VALUES (?,?)', [$clinicId, $insId]); } // خدمات کلینیک foreach ([101, 102, 103, 201, 202, 203, 801, 802, 803] as $svcId) { $conn->executeStatement('INSERT IGNORE INTO clinic_services (clinic_id, service_id) VALUES (?,?)', [$clinicId, $svcId]); } echo "✅ کلینیک امید تبریز ایجاد شد (id: $clinicId)\n\n"; // ───────────────────────────────────────────────────────────────────────────── // بخش C — دکتر نمونه کامل (تبریز) // ───────────────────────────────────────────────────────────────────────────── echo "👨‍⚕️ ایجاد دکتر نمونه...\n"; $sampleDocMobile = nextMobile(); $sampleDocUserUuid = newUuid(); $conn->executeStatement( 'INSERT INTO users (uuid, mobile_number, password_hash, real_name, roles, status, created_at, updated_at) VALUES (?,?,?,?,?,1,?,?)', [$sampleDocUserUuid, $sampleDocMobile, $passwordHash, 'دکتر آرمان رضایی', '["ROLE_USER","ROLE_DOCTOR"]', $now, $now] ); $sampleDocUserId = (int) $conn->lastInsertId(); $sampleDocUuid = newUuid(); $conn->executeStatement( 'INSERT INTO doctors (uuid, user_id, name, gender, medical_system_code, mobile_number, activity_time, degree, info, doctor_rate, doctor_rate_percentage, active_doctor_appointment, representation_id, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)', [ $sampleDocUuid, $sampleDocUserId, 'دکتر آرمان رضایی', 'man', 'IR-10001', $sampleDocMobile, mktime(0, 0, 0, 1, 1, 2008), 'specialist', 'متخصص قلب و عروق با بیش از ۱۶ سال سابقه بالینی. فارغ‌التحصیل دانشگاه علوم پزشکی تبریز با فلوشیپ قلب از دانشگاه تهران. عضو انجمن قلب ایران و مولف بیش از ۳۰ مقاله علمی در مجلات معتبر بین‌المللی. دارای تخصص ویژه در آنژیوگرافی تشخیصی و درمانی، اکوکاردیوگرافی و درمان نارسایی قلبی.', 4.8, 96.0, 101, $now, $now, ] ); $sampleDocId = (int) $conn->lastInsertId(); // تخصص‌ها foreach ([2, 3] as $specId) { $conn->executeStatement('INSERT IGNORE INTO doctor_specialties (doctor_id, specialty_id) VALUES (?,?)', [$sampleDocId, $specId]); } // خدمات foreach ([101, 102, 103, 104, 110] as $svcId) { $conn->executeStatement('INSERT IGNORE INTO doctor_expertise (doctor_id, service_id) VALUES (?,?)', [$sampleDocId, $svcId]); } // بیمه‌ها foreach ([1, 2, 3, 7] as $insId) { $conn->executeStatement('INSERT IGNORE INTO doctor_insurances (doctor_id, insurance_id) VALUES (?,?)', [$sampleDocId, $insId]); } // شهر و استان $conn->executeStatement('INSERT IGNORE INTO doctor_cities (doctor_id, city_id) VALUES (?,?)', [$sampleDocId, 101]); $conn->executeStatement('INSERT IGNORE INTO doctor_provinces (doctor_id, province_id) VALUES (?,?)', [$sampleDocId, 1]); // آدرس مطب شخصی $addrUuid1 = newUuid(); $conn->executeStatement( 'INSERT INTO doctor_addresses (uuid, doctor_id, clinic_id, city_id, province_id, type, name, address, telephone, created_at, updated_at) VALUES (?,?,NULL,?,?,?,?,?,?,?,?)', [ $addrUuid1, $sampleDocId, 101, 1, 'personal', 'مطب دکتر رضایی', 'تبریز، خیابان آزادی، کوچه پانزدهم، ساختمان پارسیان، واحد ۱۲', '04132001122', $now, $now, ] ); $addrId1 = (int) $conn->lastInsertId(); // آدرس کلینیک $addrUuid2 = newUuid(); $conn->executeStatement( 'INSERT INTO doctor_addresses (uuid, doctor_id, clinic_id, city_id, province_id, type, name, address, telephone, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)', [ $addrUuid2, $sampleDocId, $clinicId, 101, 1, 'clinic', 'کلینیک تخصصی امید تبریز', 'تبریز، خیابان ارتش، نبش کوچه سوم، ساختمان امید، طبقه اول', '04133445566', $now, $now, ] ); $addrId2 = (int) $conn->lastInsertId(); // clinic_doctors $conn->executeStatement('INSERT IGNORE INTO clinic_doctors (clinic_id, doctor_id) VALUES (?,?)', [$clinicId, $sampleDocId]); // برنامه کاری (هر دو مطب — مطب اصلی) $scheduleJson = makeSchedule($addrId1, true); $scheduleUuid = newUuid(); $conn->executeStatement( 'INSERT INTO weekly_schedules (uuid, doctor_id, setting, created_at, updated_at) VALUES (?,?,?,?,?)', [$scheduleUuid, $sampleDocId, $scheduleJson, $now, $now] ); // منشی دکتر نمونه $secMobile = nextMobile(); $secUserUuid = newUuid(); $conn->executeStatement( 'INSERT INTO users (uuid, mobile_number, password_hash, real_name, roles, status, created_at, updated_at) VALUES (?,?,?,?,?,1,?,?)', [$secUserUuid, $secMobile, $passwordHash, 'خانم نرگس صادقی', '["ROLE_USER","ROLE_SECRETARY"]', $now, $now] ); $secUserId = (int) $conn->lastInsertId(); $secUuid = newUuid(); $conn->executeStatement( 'INSERT INTO doctor_secretaries (uuid, doctor_id, secretary_id, active, owner_type, clinic_id, created_at, updated_at) VALUES (?,?,?,1,?,NULL,?,?)', [$secUuid, $sampleDocId, $secUserId, 'doctor', $now, $now] ); echo "✅ دکتر نمونه (آرمان رضایی) ایجاد شد (id: $sampleDocId)\n"; echo " 📍 مطب: id=$addrId1 | کلینیک امید: id=$addrId2\n"; echo " 👩‍💼 منشی: خانم نرگس صادقی (موبایل: $secMobile)\n\n"; // ───────────────────────────────────────────────────────────────────────────── // بخش D — ۱۰۰ دکتر به ازای هر شهر (bulk) // ───────────────────────────────────────────────────────────────────────────── $targetCities = [101, 102, 103, 104, 105, 108, 111, 113, 117, 121, 122, 126, 128, 131, 132]; $totalCreated = 0; foreach ($targetCities as $cityId) { $provincId = $cityProvince[$cityId]; $cityName = $cityNames[$cityId]; $docCount = 0; echo "🏙️ $cityName: "; // flat list of 100 doctors from specialty groups $doctorQueue = []; foreach ($specialtyGroups as $group) { for ($n = 0; $n < $group['count']; $n++) { $doctorQueue[] = $group; } } $nameIdx = 0; foreach ($doctorQueue as $idx => $group) { // تعیین جنسیت if ($group['gender_mix'] === 'female') { $gender = 'woman'; $firstName = $femaleFirstNames[$nameIdx % count($femaleFirstNames)]; } elseif ($group['gender_mix'] === 'male') { $gender = 'man'; $firstName = $maleFirstNames[$nameIdx % count($maleFirstNames)]; } else { $gender = ($idx % 3 === 0) ? 'woman' : 'man'; $firstName = ($gender === 'woman') ? $femaleFirstNames[$nameIdx % count($femaleFirstNames)] : $maleFirstNames[$nameIdx % count($maleFirstNames)]; } $lastName = $lastNames[$nameIdx % count($lastNames)]; $nameIdx++; $primarySpec = $group['specs'][0]; $specLabel = $specNames[$primarySpec] ?? 'پزشک'; $degreeLabel = $degreeLabels[$group['degree']] ?? 'متخصص'; $title = ($gender === 'woman') ? 'دکتر' : 'دکتر'; $fullName = "$title $firstName $lastName"; $mobile = nextMobile(); $userUuid = newUuid(); $conn->executeStatement( 'INSERT INTO users (uuid, mobile_number, password_hash, real_name, roles, status, created_at, updated_at) VALUES (?,?,?,?,?,1,?,?)', [$userUuid, $mobile, $passwordHash, $fullName, '["ROLE_USER","ROLE_DOCTOR"]', $now, $now] ); $userId = (int) $conn->lastInsertId(); $rate = round(3.5 + mt_rand(0, 15) / 10, 1); $ratePercentage = $rate * 20.0; $startYear = 1995 + mt_rand(0, 20); $medCode = 'IR-' . str_pad((string)(10001 + $totalCreated + $docCount), 6, '0', STR_PAD_LEFT); $info = "$degreeLabel $specLabel. فارغ‌التحصیل دانشگاه علوم پزشکی $cityName. " . "با " . (date('Y') - $startYear) . " سال سابقه بالینی در حوزه $specLabel. " . "پذیرش بیمه‌های تامین اجتماعی و خدمات درمانی."; $docUuid = newUuid(); $conn->executeStatement( 'INSERT INTO doctors (uuid, user_id, name, gender, medical_system_code, mobile_number, activity_time, degree, info, doctor_rate, doctor_rate_percentage, active_doctor_appointment, representation_id, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)', [ $docUuid, $userId, $fullName, $gender, $medCode, $mobile, mktime(0, 0, 0, 1, 1, $startYear), $group['degree'], $info, $rate, $ratePercentage, $cityId, $now, $now, ] ); $docId = (int) $conn->lastInsertId(); // تخصص‌ها foreach ($group['specs'] as $specId) { $conn->executeStatement('INSERT IGNORE INTO doctor_specialties (doctor_id, specialty_id) VALUES (?,?)', [$docId, $specId]); } // خدمات (حداکثر ۳ خدمت) $services = array_slice($group['services'], 0, 3); foreach ($services as $svcId) { $conn->executeStatement('INSERT IGNORE INTO doctor_expertise (doctor_id, service_id) VALUES (?,?)', [$docId, $svcId]); } // بیمه‌ها: پایه + یک تکمیلی تصادفی $suppInsId = $supplementaryInsurances[mt_rand(0, count($supplementaryInsurances) - 1)]; foreach (array_unique([1, 2, $suppInsId]) as $insId) { $conn->executeStatement('INSERT IGNORE INTO doctor_insurances (doctor_id, insurance_id) VALUES (?,?)', [$docId, $insId]); } // شهر و استان $conn->executeStatement('INSERT IGNORE INTO doctor_cities (doctor_id, city_id) VALUES (?,?)', [$docId, $cityId]); $conn->executeStatement('INSERT IGNORE INTO doctor_provinces (doctor_id, province_id) VALUES (?,?)', [$docId, $provincId]); // آدرس مطب $streetNum = mt_rand(1, 50); $buildingNo = mt_rand(1, 30); $addrUuid = newUuid(); $conn->executeStatement( 'INSERT INTO doctor_addresses (uuid, doctor_id, clinic_id, city_id, province_id, type, name, address, telephone, created_at, updated_at) VALUES (?,?,NULL,?,?,?,?,?,?,?,?)', [ $addrUuid, $docId, $cityId, $provincId, 'personal', "مطب $fullName", $cityName . '، خیابان شهید بهشتی، کوچه ' . $streetNum . '، پلاک ' . $buildingNo, '0' . (4100000000 + mt_rand(10000000, 99999999)), $now, $now, ] ); $addrId = (int) $conn->lastInsertId(); // برنامه کاری $schedJson = makeSchedule($addrId, $idx % 4 !== 0); $schedUuid = newUuid(); $conn->executeStatement( 'INSERT INTO weekly_schedules (uuid, doctor_id, setting, created_at, updated_at) VALUES (?,?,?,?,?)', [$schedUuid, $docId, $schedJson, $now, $now] ); $docCount++; } $totalCreated += $docCount; echo "$docCount دکتر ایجاد شد ✅\n"; } echo "\n✅ پایان — مجموع $totalCreated دکتر در " . count($targetCities) . " شهر ایجاد شد\n"; echo "📱 رمز عبور همه کاربران: Test@1234\n"; echo "📱 موبایل اول دکتر نمونه: $sampleDocMobile\n";