בעת השקת הזמנה מקוונת במרכז רפואי על 1C-Bitrix, עולה בעיה נפוצה אחת: 1C:Medicina אינה מספקת נתונים בזמן אמת. הרופאים מנהלים את לוחות הזמנים ב-1C, אך באתר זה מתעדכן רק לאחר שעות. סנכרון באמצעות החלפת קבצים או שאילתות ישירות למסד הנתונים של 1C מוביל לשגיאות ועיכובים. אנו פותרים זאת באמצעות שירותי HTTP — פרוטוקול מודרני המבטיח אינטראקציה חלקה בין המערכות.
1C:Medicina היא משפחת תצורות עבור ארגונים רפואיים: "בית חולים", "מרפאה", "מעבדה רפואית". תצורות אלה רצות על פלטפורמת 1C:Enterprise 8, ובניגוד לרוב מערכות המידע הרפואיות האחרות, הן מוכרות היטב למפתחים העובדים במערכת האקולוגית של 1C. הניסיון שלנו כולל למעלה מ-10 שנים של אינטגרציות 1C-Bitrix עם מערכות מידע רפואיות, עם יותר מ-50 פרויקטים שיושמו במוסדות רפואיים. עלות הפיתוח תלויה במורכבות התצורה ובמספר ספריות המסונכרנות, אך אינטגרציה מתוכננת כראוי מאפשרת הפחתת עלויות התפעול של מרפאה באמצעות אוטומציה של הזמנות.
מדוע שירותי HTTP עדיפים על אובייקט COM?
אובייקט COM — קריאה ישירה ל-1C מ-PHP באמצעות new COM(...). זה עובד רק על שרת Windows ומתרחב בצורה גרועה. עם בקשות מקבילות (5+ מטופלים בו-זמנית), מתרחשות נעילות, וכתוצאה מכך ירידה של פי 3–5 בביצועים בהשוואה לשירותי HTTP. שירותי HTTP אינם תלויים במערכת ההפעלה, תומכים בעיבוד אסינכרוני ובשמירה במטמון בצד של Bitrix. מסד נתונים ביניים — חלופה אם 1C כבר מייצא נתונים ל-PostgreSQL/MySQL, אך היא אינה מספקת חילופי נתונים דו-כיווניים בזמן אמת. שירותי HTTP הם האפשרות המועדפת.
| שיטה | מהירות | אמינות | מורכבות |
|---|---|---|---|
| שירותי HTTP של 1C | גבוהה | גבוהה | בינונית |
| אובייקט COM | בינונית (יורדת בעומס) | נמוכה (נעילות) | נמוכה |
| מסד נתונים ביניים | נמוכה (אסינכרוני) | גבוהה | גבוהה |
שירות HTTP ב-1C:Medicina
בקונפיגורטור של 1C, נוצר שירות HTTP (כללי → שירותי HTTP):
Имя: МедицинскийAPI КорневойURL: /medapi Версия: 1.0.0 מתודות (תבניות URL):
-
Имя: МедицинскийAPI КорневойURL: /medapi Версия: 1.0.0— רשימת רופאים -
GET /medapi/doctors— לוח הזמנים של הרופא -
GET /medapi/schedule/{doctorId}/{date}— יצירת פגישה -
POST /medapi/appointments— ביטול פגישה
מתודת טיפול ב-1C (שפת מובנית):
Функция ПолучитьРасписание(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки["Content-Type"] = "application/json; charset=utf-8";
ИдВрача = Запрос.ПараметрыURL["doctorId"];
ДатаСеанса = Дата(Запрос.ПараметрыURL["date"]);
// Запрос к регистру расписания
Запрос1С = Новый Запрос();
Запрос1С.Текст = "
|ВЫБРАТЬ
| РасписаниеВрачей.ВремяНачала,
| РасписаниеВрачей.ВремяОкончания,
| РасписаниеВрачей.СтатусЯчейки,
| РасписаниеВрачей.КабинетПоликлиники
|ИЗ
| РегистрСведений.РасписаниеВрачей КАК РасписаниеВрачей
|ГДЕ
| РасписаниеВрачей.Врач.УникальныйИдентификатор = &ИдВрача
| И РасписаниеВрачей.Дата = &Дата
| И РасписаниеВрачей.СтатусЯчейки = Перечисления.СтатусыЯчеекРасписания.Свободна";
Запрос1С.УстановитьПараметр("ИдВрача", ИдВрача);
Запрос1С.УстановитьПараметр("Дата", ДатаСеанса);
Результат = Запрос1С.Выполнить().Выбрать();
Слоты = Новый Массив();
Пока Результат.Следующий() Цикл
СлотДанные = Новый Структура("start,end,cabinet");
СлотДанные.start = Формат(Результат.ВремяНачала, "ДФ=HH:mm");
СлотДанные.end = Формат(Результат.ВремяОкончания, "ДФ=HH:mm");
СлотДанные.cabinet = Результат.КабинетПоликлиники.Номер;
Слоты.Добавить(СлотДанные);
КонецЦикла;
Ответ.УстановитьТелоИзСтроки(ЗаписатьJSON(Слоты));
Возврат Ответ;
КонецФункции לקוח PHP עבור שירות HTTP של 1C:Medicina
class OneCMedicinaClient {
private string $baseUrl; // http://1c-server:8080/медицина/hs/medapi
private string $username;
private string $password;
public function getSchedule(string $doctorGuid, string $date): array {
return $this->request('GET', "/schedule/{$doctorGuid}/{$date}");
}
public function createAppointment(array $data): array {
return $this->request('POST', '/appointments', [
'slotDate' => $data['date'],
'slotTime' => $data['time'],
'doctorGuid' => $data['doctor_guid'],
'patient' => [
'lastName' => $data['last_name'],
'firstName' => $data['first_name'],
'middleName' => $data['middle_name'] ?? '',
'birthDate' => $data['birth_date'],
'phone' => $data['phone'],
'email' => $data['email'],
'snils' => $data['snils'] ?? '',
],
'serviceCode' => $data['service_code'] ?? '',
]);
}
private function request(string $method, string $path, array $body = []): array {
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_USERPWD => "{$this->username}:{$this->password}", // Basic Auth в 1С
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_POSTFIELDS => $body ? json_encode($body, JSON_UNESCAPED_UNICODE) : null,
CURLOPT_TIMEOUT => 10,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("1C:Медицина API error {$httpCode}");
}
return json_decode($json, true) ?? [];
}
}חשוב: 1C:Enterprise כברירת מחדל אינה תומכת בבקשות מקבילות לבסיס מידע יחיד ללא רישיונות חיבור לקוח. בעומס גבוה, נדרשת בריכת חיבורים או שמירה במטמון בצד של Bitrix.
כיצד לסנכרן ספריות ללא כפילויות?
רשימת הרופאים, התמחויותיהם, החדרים — אנו מסנכרנים מ-1C לבלוק מידע של Bitrix. פרמטר המפתח הוא המזהה הייחודי של הרופא (GUID) מ-1C. הוא נשמר במאפיין בלוק המידע, ובמהלך סנכרון מחדש איננו יוצרים כפילויות אלא מעדכנים אלמנטים קיימים. טעות אופיינית היא אובדן הקשר בין רשומות כאשר המזהה משתנה ב-1C. אנו משתמשים במאפיין הפנימי DELETE /medapi/appointments/{id} ובלוגיקת חיפוש המבוססת עליו.
class OneCMedicDoctorSync
{
public function syncDoctors(): void
{
$doctors = $this->onecClient->request('GET', '/doctors');
foreach ($doctors as $doctor) {
$existingId = $this->findDoctorByGuid($doctor['guid']);
$fields = [
'NAME' => $doctor['fullName'],
'ACTIVE' => $doctor['active'] ? 'Y' : 'N',
'IBLOCK_ID' => DOCTORS_IBLOCK_ID,
'IBLOCK_SECTION_ID' => $this->getSpecializationSectionId($doctor['specialization']),
];
$props = [
'DOCTOR_GUID' => $doctor['guid'],
'SPECIALIZATION' => $doctor['specialization'],
'CABINET_NUMBER' => $doctor['cabinet'],
'EXPERIENCE_YEARS' => $doctor['experienceYears'],
'ACADEMIC_DEGREE' => $doctor['academicDegree'],
];
if ($existingId) {
$el = new \CIBlockElement();
$el->Update($existingId, $fields);
\CIBlockElement::SetPropertyValuesEx($existingId, DOCTORS_IBLOCK_ID, $props);
} else {
$el = new \CIBlockElement();
$newId = $el->Add(array_merge($fields, ['PROPERTY_VALUES' => $props]));
}
}
}
} אילו נתונים מסונכרנים בין 1C:Medicina ל-Bitrix?
| נתונים | כיוון | תדירות |
|---|---|---|
| רופאים (שם, התמחות, חדר) | 1C → Bitrix | בעת אירוע (שינוי ב-1C) |
| לוח זמנים (משבצות זמן) | 1C → Bitrix | לעתים רחוקות יותר: כל 5-15 דקות |
| פגישת מטופל חדשה | Bitrix → 1C | מיידית (מקוון) |
| ביטול פגישה | Bitrix → 1C | מיידית |
| שירותים ומחירים | 1C → Bitrix | מתוזמן (פעם ביום) |
מה כלול בעבודה
- ניתוח התצורה הספציפית של 1C:Medicina והרישומים הזמינים
- פיתוח שירות HTTP בצד 1C (במשותף עם מפתח 1C)
- לקוח PHP עבור שירות HTTP עם שמירה במטמון (שמירה במטמון מתויגת)
- סנכרון ספריית הרופאים לבלוק המידע של Bitrix
- רכיב הזמנה מקוון עם טופס (ולידציה, בחירת משבצת)
- הודעות למטופלים באמצעות SMS/דוא"ל לאחר ההזמנה
- תיעוד אינטגרציה והדרכה
- 3 חודשים של תמיכה באחריות
רשימת בדיקה של שלבי פרויקט טיפוסיים
- ביקורת על תצורת 1C:Medicina וסכימת הנתונים
- עיצוב REST API (שירות HTTP)
- פיתוח ובדיקת שירות HTTP ב-1C
- יצירת לקוח PHP ורכיבי Bitrix
- בדיקות אינטגרציה (עד שבועיים)
- השקה ותמיכה (3 חודשים אחריות)
ציר זמן: 6–10 שבועות כאשר מפתח 1C נמצא בצוות. פיתוח שירות HTTP בצד 1C אורך 2–4 שבועות, החלק של PHP אורך 3–6 שבועות. אינטגרציה מתוכננת כראוי חוסכת בתקציב התמיכה ומפחיתה עלויות ניהול. קבלו הערכה ראשונית של הפרויקט שלכם — אנו ננתח את התצורה ונציע פתרון. צרו קשר.

