Налаштування інтеграції з лабораторними інформаційними системами 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Налаштування інтеграції з лабораторними інформаційними системами 1С-Бітрікс
Проста
~1 робочий день
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Налаштування інтеграції з лабораторними інформаційними системами 1С-Бітрікс

Лабораторія приймає аналізи онлайн та через пункти збору. Результати готуються в лабораторній інформаційній системі (ЛІС) — спеціалізованому ПЗ для управління зразками, аналітичним обладнанням та результатами. Пацієнт хоче отримувати результати в особистому кабінеті на сайті, а не чекати паперового бланку або телефонувати на гарячу лінію. Завдання: опублікувати результати аналізів із ЛІС в особистому кабінеті 1С-Бітрікс.

Поширені ЛІС у Росії

  • QLAB (Кваліаб) — одна з найпоширеніших, REST API
  • CaLab — орієнтована на приватні лабораторії, REST/SOAP
  • LIMS (власні розробки) — у великих лабораторій часто кастомні системи
  • MedWork / Ераліс — REST API
  • Helix Lab — закрита система, інтеграція лише для партнерів

API у всіх різні. Об'єднує їх структура даних: направлення (замовлення) → зразки → тести → результати.

Модель даних лабораторних замовлень

-- Замовлення на аналізи
CREATE TABLE local_lab_orders (
    ID              BIGINT AUTO_INCREMENT PRIMARY KEY,
    USER_ID         INT NOT NULL,
    EXTERNAL_ORDER_ID VARCHAR(100) NOT NULL UNIQUE,  -- ID у ЛІС
    ORDER_DATE      DATE,
    STATUS          ENUM('received','processing','completed','cancelled') DEFAULT 'received',
    SYNCED_AT       DATETIME,
    INDEX idx_user (USER_ID),
    INDEX idx_external (EXTERNAL_ORDER_ID)
);

-- Результати тестів
CREATE TABLE local_lab_results (
    ID              BIGINT AUTO_INCREMENT PRIMARY KEY,
    ORDER_ID        BIGINT NOT NULL,
    TEST_CODE       VARCHAR(50),   -- код тесту (МКБ / LOINC / власний)
    TEST_NAME       VARCHAR(500),
    RESULT_VALUE    VARCHAR(500),  -- текстове значення (число, +/-, текст)
    RESULT_UNIT     VARCHAR(100),  -- одиниця вимірювання
    REFERENCE_MIN   VARCHAR(100),  -- референсний мінімум
    REFERENCE_MAX   VARCHAR(100),  -- референсний максимум
    IS_ABNORMAL     CHAR(1) DEFAULT 'N', -- вихід за референс
    RESULT_DATE     DATETIME,
    PDF_PATH        VARCHAR(500),  -- шлях до PDF-бланку
    INDEX idx_order (ORDER_ID)
);

Клієнт ЛІС API (на прикладі QLAB)

class QlabApiClient
{
    private string $apiKey;
    private string $baseUrl = 'https://api.qlab.ru/v2';

    public function getOrdersByPatient(string $patientPhone, string $dateFrom): array
    {
        return $this->request('GET', '/orders', [
            'patient_phone' => $patientPhone,
            'date_from'     => $dateFrom,
            'status'        => 'completed',
        ]);
    }

    public function getOrderResults(string $orderId): array
    {
        return $this->request('GET', "/orders/{$orderId}/results");
    }

    public function getResultPdf(string $orderId): string
    {
        // Повертає бінарний PDF
        $response = $this->rawRequest('GET', "/orders/{$orderId}/pdf");
        return $response;
    }

    public function createOrder(array $patientData, array $tests): array
    {
        return $this->request('POST', '/orders', [
            'patient'   => $patientData,
            'tests'     => $tests,
            'source'    => 'website',
        ]);
    }

    private function request(string $method, string $path, array $data = []): array
    {
        $url = $this->baseUrl . $path;
        if ($method === 'GET' && $data) {
            $url .= '?' . http_build_query($data);
        }

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_HTTPHEADER     => [
                "X-Api-Key: {$this->apiKey}",
                'Accept: application/json',
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => $method === 'POST' ? json_encode($data) : null,
        ]);

        $json     = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 400) {
            throw new \RuntimeException("QLAB API error {$httpCode}: {$json}");
        }

        return json_decode($json, true) ?? [];
    }
}

Синхронізація результатів

Агент раз на 15 хвилин перевіряє незавершені замовлення:

function SyncLabResults(): string
{
    $qlabClient = new QlabApiClient(QLAB_API_KEY);

    // Активні замовлення без фінального статусу
    $pendingOrders = LocalLabOrdersTable::getList([
        'filter' => ['STATUS' => ['received', 'processing']],
        'select' => ['ID', 'EXTERNAL_ORDER_ID', 'USER_ID'],
    ]);

    while ($order = $pendingOrders->fetch()) {
        try {
            $lisData = $qlabClient->getOrderResults($order['EXTERNAL_ORDER_ID']);

            if (($lisData['status'] ?? '') === 'completed') {
                // Зберігаємо результати
                foreach ($lisData['results'] ?? [] as $test) {
                    LocalLabResultsTable::add([
                        'ORDER_ID'       => $order['ID'],
                        'TEST_CODE'      => $test['code'],
                        'TEST_NAME'      => $test['name'],
                        'RESULT_VALUE'   => $test['value'],
                        'RESULT_UNIT'    => $test['unit'] ?? '',
                        'REFERENCE_MIN'  => $test['ref_min'] ?? '',
                        'REFERENCE_MAX'  => $test['ref_max'] ?? '',
                        'IS_ABNORMAL'    => ($test['abnormal'] ?? false) ? 'Y' : 'N',
                        'RESULT_DATE'    => $test['result_date'],
                    ]);
                }

                // Завантажуємо та зберігаємо PDF
                $pdf     = $qlabClient->getResultPdf($order['EXTERNAL_ORDER_ID']);
                $pdfPath = "/upload/lab-results/{$order['USER_ID']}/{$order['EXTERNAL_ORDER_ID']}.pdf";
                file_put_contents($_SERVER['DOCUMENT_ROOT'] . $pdfPath, $pdf);

                // Оновлюємо статус
                LocalLabOrdersTable::update($order['ID'], [
                    'STATUS'    => 'completed',
                    'SYNCED_AT' => new \Bitrix\Main\Type\DateTime(),
                ]);

                // Повідомляємо пацієнта
                $user = \Bitrix\Main\UserTable::getById($order['USER_ID'])->fetch();
                \CEvent::Send('LAB_RESULTS_READY', SITE_ID, [
                    'EMAIL'      => $user['EMAIL'],
                    'NAME'       => $user['NAME'],
                    'ORDER_ID'   => $order['EXTERNAL_ORDER_ID'],
                    'RESULT_URL' => '/personal/lab-results/' . $order['ID'] . '/',
                ]);
            }
        } catch (\Exception $e) {
            \CEventLog::Add([
                'SEVERITY'    => 'WARNING',
                'AUDIT_TYPE_ID' => 'LAB_SYNC',
                'DESCRIPTION' => "Order {$order['EXTERNAL_ORDER_ID']}: {$e->getMessage()}",
            ]);
        }
    }

    return __FUNCTION__ . '();';
}

Компонент «Мої аналізи» в особистому кабінеті

class LabResultsComponent extends CBitrixComponent
{
    public function executeComponent(): void
    {
        $userId = (int)\Bitrix\Main\Engine\CurrentUser::get()->getId();

        $orders = LocalLabOrdersTable::getList([
            'filter' => ['USER_ID' => $userId],
            'order'  => ['ID' => 'DESC'],
            'select' => ['ID', 'EXTERNAL_ORDER_ID', 'ORDER_DATE', 'STATUS'],
        ])->fetchAll();

        // Для кожного виконаного замовлення — результати
        foreach ($orders as &$order) {
            if ($order['STATUS'] === 'completed') {
                $order['RESULTS'] = LocalLabResultsTable::getList([
                    'filter' => ['ORDER_ID' => $order['ID']],
                    'order'  => ['TEST_NAME' => 'ASC'],
                ])->fetchAll();
            }
        }

        $this->arResult = ['ORDERS' => $orders, 'USER_ID' => $userId];
        $this->includeComponentTemplate();
    }
}

Безпека: доступ лише до власних результатів

Критично: перевірка USER_ID при будь-якому запиті до результатів. PDF-файли зберігаються поза webroot або з перевіркою доступу через PHP:

// /local/ajax/download-lab-result.php
$userId  = \Bitrix\Main\Engine\CurrentUser::get()->getId();
$orderId = (int)$_GET['order_id'];

$order = LocalLabOrdersTable::getList([
    'filter' => ['ID' => $orderId, 'USER_ID' => $userId],
])->fetch();

if (!$order) {
    http_response_code(403);
    exit;
}

$pdfPath = $_SERVER['DOCUMENT_ROOT'] . '/upload/lab-results/' . $userId . '/' . $order['EXTERNAL_ORDER_ID'] . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="result-' . $order['EXTERNAL_ORDER_ID'] . '.pdf"');
readfile($pdfPath);

Склад робіт

  • Аналіз API конкретної ЛІС, узгодження формату даних
  • PHP-клієнт ЛІС API
  • Таблиці замовлень і результатів
  • Агент синхронізації результатів, завантаження PDF
  • Компонент «Мої аналізи» в особистому кабінеті
  • Email-повідомлення про готовність результатів
  • Захист доступу до PDF та даних результатів

Строки: 3–5 тижнів за наявності задокументованого REST API ЛІС. 6–10 тижнів при SOAP або нестандартному протоколі.