Files
clinicpro/seed_realistic_data.php
T
hamed df7a784701 feat: implement realistic data seeding for doctors, clinics, and secretaries
- Added seed_realistic_data.php to clean existing data and populate the database with realistic entries for doctors, clinics, and secretaries.
- Created a structured approach to generate 100 doctors per city with diverse specialties and services.
- Implemented database cleanup routines to ensure a fresh start for data seeding.
- Enhanced the DoctorSecretaryRepository with improved comments for clarity.
2026-06-15 14:18:25 +03:30

440 lines
24 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
(new Symfony\Component\Dotenv\Dotenv())->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";