RU/EN EN/RU

Инструкция по интеграции утилит контроля качества

Софт А (LIMS/MES/ERP) Утилита контроля качества Софт Б (LIMS/MES/ERP)
input-*.csv output-*.json
Опционально (только для асинхронной обработки):
Софт А и Софт Б — разные системы → используйте Message Queue
Софт А и Софт Б — одна система → синхронная обработка (без очереди)
⚠️ ВАЖНО: Правила именования файлов
Чтобы избежать конфликтов при обработке одной партии несколькими утилитами, используйте формат:

input-{имяУтилиты}-{идентификаторПартии}.csv
output-{имяУтилиты}-{идентификаторПартии}.json

Пример:
input-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.csv
output-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.json

Это гарантирует, что файлы от разных утилит не перезапишут друг друга, даже если все файлы хранятся в одной папке.

Пошаговая инструкция

1 Экспорт данных в CSV

Что делает Софт А: Экспортирует данные партии в CSV-файл в формате, соответствующем выбранной утилите.

Формат файла: input-{имяУтилиты}-{идентификаторПартии}.csv

Пример: input-DecayCorrector-BATCH-001.csv

Требования:

  • Первая строка — заголовки столбцов (точно как в описании утилиты)
  • Кодировка файла: UTF-8
  • Разделитель: запятая (,)
  • Десятичный разделитель: точка (.)

2 Запуск утилиты

Команда:

{имяУтилиты}.exe input-{имяУтилиты}-{идентификаторПартии}.csv output-{имяУтилиты}-{идентификаторПартии}.json

Пример:

Fluorine18FDGQualityChecker.exe input-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.csv output-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.json

Возвращаемое значение:

  • Exit Code = 0 — утилита завершилась успешно
  • Exit Code ≠ 0 — произошла ошибка (проверьте логи утилиты)

Обработка ошибок: Утилита сама обрабатывает ошибки валидации данных. Если данные некорректны, в output.json будет поле ErrorMessage с описанием ошибки. Если ошибок нет, ErrorMessage = "".

3 Обработка результата

Что делает Софт Б: Читает JSON-файл с результатами и интегрирует их в рабочий процесс.

Файл результата: output-{имяУтилиты}-{идентификаторПартии}.json

Ключевые поля в результате:

Поле Тип Описание
ErrorMessage string Пустая строка = успех, иначе описание ошибки
Result.AllWithinLimits boolean true = все параметры в пределах нормы, false = есть отклонения
Result.Recommendation string Текстовая рекомендация («Партия годна», «Требуется повторный анализ» и т.д.)
Result.Parameters object Детальные результаты по каждому параметру контроля качества

Действия после обработки:

  • Сохранить результаты в базу данных
  • Сгенерировать отчёт для оператора
  • Обновить статус партии в системе («Прошла КК», «Не прошла КК»)
  • Отправить уведомление ответственному лицу при отклонениях

4 Опционально: Асинхронная обработка через Message Queue

Когда использовать: Только если Софт А и Софт Б — это разные системы, работающие на разных серверах.

Сценарий:

  1. Софт А создаёт файл input-*.csv
  2. Софт А формирует сообщение для очереди:
    • UtilityName — имя утилиты
    • InputFile — путь к input-файлу
    • OutputFile — путь к output-файлу
    • BatchId — идентификатор партии
  3. Софт А отправляет сообщение в очередь и продолжает работу
  4. Отдельный процесс (потребитель) читает сообщение из очереди
  5. Потребитель запускает утилиту и дожидается завершения
  6. Потребитель читает output-*.json и отправляет результат обратно в Софт Б через очередь или напрямую

Рекомендации:

  • Используйте надёжные очереди: RabbitMQ, Azure Service Bus, AWS SQS
  • Реализуйте механизм повторных попыток при сбоях
  • Добавьте таймауты для предотвращения «зависания» задач
  • Логируйте все операции для аудита

Сценарий: Разные серверы (Софт А ≠ Софт Б)

Простой вариант (рекомендуется):
Если возможно, подключите папку с файлами как сетевой диск между серверами. Это устраняет необходимость в очереди сообщений и значительно упрощает архитектуру.

1 Общая структура сообщения для очереди

Формат сообщения:

Поле Тип Описание Обязательное
Sender string Имя сервера, отправившего сообщение Да
Receiver string Имя сервера-получателя (куда отправить результат) Да
UtilityName string Имя утилиты контроля качества Да
BatchId string Уникальный идентификатор партии Да
InputFileAsBytes byte[] Содержимое input-файла в байтах Да
OutputFileAsBytes byte[] Содержимое output-файла в байтах (может быть null) Нет

Важно: Пути к файлам (InputFile, OutputFile) не передаются — только содержимое файлов в виде байтов. Это обеспечивает независимость от файловой системы каждого сервера.

Сценарий 1: Утилиты на сервере Софт А

┌─────────────────────────────────────────────────────────────┐
│  Сервер А (Софт А + Утилиты):                               │
│  1. Создать input-{util}-{batch}.csv                        │
│  2. Выполнить утилиту → output-{util}-{batch}.json          │
│  3. Прочитать оба файла в байты                             │
│  4. Сформировать сообщение:                                 │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [байты input файла]                │
│     • OutputFileAsBytes = [байты output файла]              │
│  5. Отправить сообщение в очередь                           │
│  6. Продолжить работу (не ждать ответа)                     │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Сервер Б (Софт Б):                                         │
│  7. Прочитать сообщение из очереди                          │
│  8. Сохранить InputFileAsBytes → input-{util}-{batch}.csv   │
│  9. Сохранить OutputFileAsBytes → output-{util}-{batch}.json│
│  10. Обработать результат (обновить статус партии и т.д.)   │
└─────────────────────────────────────────────────────────────┘

Сценарий 2: Утилиты на сервере Софт Б

┌─────────────────────────────────────────────────────────────┐
│  Сервер А (Софт А):                                         │
│  1. Создать input-{util}-{batch}.csv                        │
│  2. Прочитать файл в байты                                  │
│  3. Сформировать сообщение:                                 │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [байты input файла]                │
│     • OutputFileAsBytes = null                              │
│  4. Отправить сообщение в очередь                           │
│  5. Продолжить работу                                       │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Сервер Б (Софт Б + Утилиты):                               │
│  6. Прочитать сообщение из очереди                          │
│  7. Сохранить InputFileAsBytes → input-{util}-{batch}.csv   │
│  8. Выполнить утилиту → output-{util}-{batch}.json          │
│  9. Прочитать результат и обработать                        │
└─────────────────────────────────────────────────────────────┘

Сценарий 3: Утилиты на отдельном сервере (Сервер В)

┌─────────────────────────────────────────────────────────────┐
│  Сервер А (Софт А):                                         │
│  1. Создать input-{util}-{batch}.csv                        │
│  2. Прочитать файл в байты                                  │
│  3. Сформировать сообщение:                                 │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerV"                                  │
│     • InputFileAsBytes = [байты input файла]                │
│     • OutputFileAsBytes = null                              │
│  4. Отправить сообщение в очередь                           │
│  5. Продолжить работу                                       │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Сервер В (Софт В + Утилиты):                               │
│  6. Прочитать сообщение из очереди                          │
│  7. Сохранить InputFileAsBytes → input-{util}-{batch}.csv   │
│  8. Выполнить утилиту → output-{util}-{batch}.json          │
│  9. Прочитать результат в байты                             │
│  10. Сформировать новое сообщение:                          │
│     • Sender = "ServerV"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [байты input файла]                │
│     • OutputFileAsBytes = [байты output файла]              │
│  11. Отправить сообщение в очередь                          │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Сервер Б (Софт Б):                                         │
│  12. Прочитать сообщение из очереди                         │
│  13. Сохранить файлы и обработать результат                 │
└─────────────────────────────────────────────────────────────┘
⚠️ Требования к приложению Софт В (если утилиты на отдельном сервере):

На сервере с утилитами должно быть запущено приложение (Софт В), которое:
  • Читает сообщения из очереди
  • Выполняет утилиты контроля качества
  • Формирует и отправляет результаты обратно в очередь
  • Логирует все операции для аудита

Примечание: Приложение Софт В может быть разработано вами, нами или другим подрядчиком. Мы можем предоставить пример реализации на C# или Python.

Сравнение сценариев

Сценарий Преимущества Недостатки Когда использовать
Сетевой диск • Простота реализации
• Не нужна очередь сообщений
• Зависимость от сетевой файловой системы Когда серверы в одной сети и можно настроить общий доступ к файлам
Утилиты на сервере А • Софт А управляет всем процессом
• Софт Б только получает результат
• Нагрузка на сервер А Когда сервер А мощный, а сервер Б только для отображения результатов
Утилиты на сервере Б • Разгрузка сервера А • Софт Б должен уметь запускать утилиты Когда сервер Б ближе к лаборатории (где генерируются данные)
Отдельный сервер В • Максимальная гибкость и масштабируемость • Требуется дополнительное приложение Софт В Когда утилиты должны быть изолированы или когда много серверов А/Б
Рекомендация:
Начните с простого сценария (сетевой диск или утилиты на одном из существующих серверов).
Переходите к отдельному серверу В только при необходимости масштабирования или изоляции.

Критические требования

1. Уникальность имён файлов
Всегда используйте формат input-{имяУтилиты}-{идентификаторПартии}.csv и output-{имяУтилиты}-{идентификаторПартии}.json.
Это предотвращает конфликты при обработке одной партии несколькими утилитами одновременно.
2. Обработка ошибок
Утилита всегда возвращает Exit Code = 0 при успешном запуске (даже если данные не прошли валидацию).
Проверяйте поле ErrorMessage в output.json для определения ошибок валидации данных.
3. Временные ограничения
Утилиты работают быстро (обычно < 1 секунды), но для надёжности установите таймаут 30-60 секунд на выполнение.
4. Безопасность
Утилиты не требуют прав администратора и работают локально. Никакие данные не передаются в интернет.
Запросить примеры интеграции

Integration Guide for QC Utilities

Software A (LIMS/MES/ERP) QC Utility Software B (LIMS/MES/ERP)
input-*.csv output-*.json
Optional (for asynchronous processing only):
Software A and Software B are different systems → use Message Queue
Software A and Software B are the same system → synchronous processing (no queue needed)
⚠️ IMPORTANT: File Naming Rules
To avoid conflicts when processing a single batch with multiple utilities, use the format:

input-{utilityName}-{batchId}.csv
output-{utilityName}-{batchId}.json

Example:
input-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.csv
output-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.json

This ensures files from different utilities won't overwrite each other, even if all files are stored in the same folder.

Step-by-Step Integration Guide

1 Export Data to CSV

What Software A does: Exports batch data to a CSV file in the format required by the selected utility.

File format: input-{utilityName}-{batchId}.csv

Example: input-DecayCorrector-BATCH-001.csv

Requirements:

  • First line — column headers (exactly as specified in utility documentation)
  • File encoding: UTF-8
  • Delimiter: comma (,)
  • Decimal separator: period (.)

2 Run the Utility

Command:

{utilityName}.exe input-{utilityName}-{batchId}.csv output-{utilityName}-{batchId}.json

Example:

Fluorine18FDGQualityChecker.exe input-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.csv output-Fluorine18FDGQualityChecker-F18-FDG-2026-03-18-A.json

Return value:

  • Exit Code = 0 — utility completed successfully
  • Exit Code ≠ 0 — error occurred (check utility logs)

Error handling: The utility handles data validation errors internally. If data is invalid, the output.json will contain an ErrorMessage field with error description. If no errors, ErrorMessage = "".

3 Process the Result

What Software B does: Reads the JSON result file and integrates it into the workflow.

Result file: output-{utilityName}-{batchId}.json

Key fields in result:

Field Type Description
ErrorMessage string Empty string = success, otherwise error description
Result.AllWithinLimits boolean true = all parameters within limits, false = deviations found
Result.Recommendation string Text recommendation ("Batch approved", "Repeat analysis required", etc.)
Result.Parameters object Detailed results for each QC parameter

Actions after processing:

  • Save results to database
  • Generate report for operator
  • Update batch status in system ("QC Passed", "QC Failed")
  • Send notification to responsible person for deviations

4 Optional: Asynchronous Processing via Message Queue

When to use: Only if Software A and Software B are different systems running on different servers.

Scenario:

  1. Software A creates input-*.csv file
  2. Software A forms queue message:
    • UtilityName — utility name
    • InputFile — path to input file
    • OutputFile — path to output file
    • BatchId — batch identifier
  3. Software A sends message to queue and continues working
  4. Separate process (consumer) reads message from queue
  5. Consumer runs utility and waits for completion
  6. Consumer reads output-*.json and sends result back to Software B via queue or directly

Recommendations:

  • Use reliable queues: RabbitMQ, Azure Service Bus, AWS SQS
  • Implement retry mechanism for failures
  • Add timeouts to prevent task "hanging"
  • Log all operations for audit purposes

Scenario: Different Servers (Software A ≠ Software B)

Simple option (recommended):
If possible, mount the file folder as a network drive between servers. This eliminates the need for a message queue and significantly simplifies the architecture.

1 General Message Structure for Queue

Message format:

Field Type Description Required
Sender string Name of server sending the message Yes
Receiver string Name of recipient server (where to send result) Yes
UtilityName string Name of QC utility Yes
BatchId string Unique batch identifier Yes
InputFileAsBytes byte[] Content of input file as bytes Yes
OutputFileAsBytes byte[] Content of output file as bytes (may be null) No

Important: File paths (InputFile, OutputFile) are NOT transmitted — only file content as bytes. This ensures independence from each server's file system.

Scenario 1: Utilities on Software A Server

┌─────────────────────────────────────────────────────────────┐
│  Server A (Software A + Utilities):                         │
│  1. Create input-{util}-{batch}.csv                         │
│  2. Run utility → output-{util}-{batch}.json                │
│  3. Read both files into bytes                              │
│  4. Form message:                                           │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [bytes of input file]              │
│     • OutputFileAsBytes = [bytes of output file]            │
│  5. Send message to queue                                   │
│  6. Continue working (don't wait for response)              │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Server B (Software B):                                     │
│  7. Read message from queue                                 │
│  8. Save InputFileAsBytes → input-{util}-{batch}.csv        │
│  9. Save OutputFileAsBytes → output-{util}-{batch}.json     │
│  10. Process result (update batch status, etc.)             │
└─────────────────────────────────────────────────────────────┘

Scenario 2: Utilities on Software B Server

┌─────────────────────────────────────────────────────────────┐
│  Server A (Software A):                                     │
│  1. Create input-{util}-{batch}.csv                         │
│  2. Read file into bytes                                    │
│  3. Form message:                                           │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [bytes of input file]              │
│     • OutputFileAsBytes = null                              │
│  4. Send message to queue                                   │
│  5. Continue working                                        │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Server B (Software B + Utilities):                         │
│  6. Read message from queue                                 │
│  7. Save InputFileAsBytes → input-{util}-{batch}.csv        │
│  8. Run utility → output-{util}-{batch}.json                │
│  9. Read result and process                                 │
└─────────────────────────────────────────────────────────────┘

Scenario 3: Utilities on Separate Server (Server V)

┌─────────────────────────────────────────────────────────────┐
│  Server A (Software A):                                     │
│  1. Create input-{util}-{batch}.csv                         │
│  2. Read file into bytes                                    │
│  3. Form message:                                           │
│     • Sender = "ServerA"                                    │
│     • Receiver = "ServerV"                                  │
│     • InputFileAsBytes = [bytes of input file]              │
│     • OutputFileAsBytes = null                              │
│  4. Send message to queue                                   │
│  5. Continue working                                        │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Server V (Software V + Utilities):                         │
│  6. Read message from queue                                 │
│  7. Save InputFileAsBytes → input-{util}-{batch}.csv        │
│  8. Run utility → output-{util}-{batch}.json                │
│  9. Read result into bytes                                  │
│  10. Form new message:                                      │
│     • Sender = "ServerV"                                    │
│     • Receiver = "ServerB"                                  │
│     • InputFileAsBytes = [bytes of input file]              │
│     • OutputFileAsBytes = [bytes of output file]            │
│  11. Send message to queue                                  │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Server B (Software B):                                     │
│  12. Read message from queue                                │
│  13. Save files and process result                          │
└─────────────────────────────────────────────────────────────┘
⚠️ Requirements for Software V Application (if utilities on separate server):

A dedicated application (Software V) must be running on the utility server that:
  • Reads messages from the queue
  • Executes QC utilities
  • Forms and sends results back to the queue
  • Logs all operations for audit purposes

Note: Software V application can be developed by you, us, or another contractor. We can provide implementation examples in C# or Python.

Scenario Comparison

Scenario Advantages Disadvantages When to use
Network Drive • Simple implementation
• No message queue needed
• Dependency on network file system When servers are on the same network and shared folder access can be configured
Utilities on Server A • Software A controls entire process
• Software B only receives result
• Load on Server A When Server A is powerful and Server B is only for result display
Utilities on Server B • Offloads Server A • Software B must be able to run utilities When Server B is closer to laboratory (where data is generated)
Separate Server V • Maximum flexibility and scalability • Requires additional Software V application When utilities must be isolated or when many Server A/B instances exist
Recommendation:
Start with a simple scenario (network drive or utilities on one of existing servers).
Move to separate Server V only when scaling or isolation is required.

Critical Requirements

1. File Name Uniqueness
Always use the format input-{utilityName}-{batchId}.csv and output-{utilityName}-{batchId}.json.
This prevents conflicts when processing a single batch with multiple utilities simultaneously.
2. Error Handling
The utility always returns Exit Code = 0 on successful launch (even if data validation fails).
Check the ErrorMessage field in output.json to determine data validation errors.
3. Time Constraints
Utilities work quickly (usually < 1 second), but for reliability set a 30-60 second timeout for execution.
4. Security
Utilities do not require administrator rights and run locally. No data is transmitted to the internet.
Request integration examples