Перейти к содержанию

Синхронизация справочников и заявок

Этот документ описывает порядок синхронизации данных между внешней системой (1С/ERP/WMS) и CARGO.RUN.
Синхронизация одинакова для обоих сценариев интеграции: когда заявка создаётся в CARGO.RUN и когда она создаётся во внешней системе.


1. Общие принципы синхронизации

Синхронизация выполняется через REST API CARGO.RUN по протоколу HTTPS с использованием токена авторизации.

Каждый объект (водитель, машина, прицеп, контрагент, организация, заявка):

  • имеет уникальный идентификатор id в CARGO.RUN;
  • при создании в CARGO.RUN возвращает этот id, который должен быть сохранён во внешней системе;
  • содержит поле updatedAt, отражающее дату и время последнего изменения.

Поле updatedAt используется как основа для инкрементальной синхронизации.

Для заявок применяйте два взаимодополняющих канала:

  • асинхронную очередь API 2.0 — для оперативного обмена;
  • GET /api/bids/GetListForExternal — для первичной загрузки, статусов, удалений и контрольной сверки.

2. Справочники, подлежащие синхронизации

2.1. Справочники, данные которых поступают из внешней системы

Эти справочники всегда считаются первичными во внешней системе:

  • Водители
  • Машины
  • Прицепы
  • Контрагенты
  • Организации

Для них внешний идентификатор является источником истины, а CARGO.RUN — получателем.

Синхронизация выполняется через методы:

  • /api/Driver/Apply, /api/Driver/Delete, /api/Driver/Restore, /api/Driver/GetList
  • /api/Car/Apply, /api/Car/Delete, /api/Car/GetList, /api/Car/GetForEdit
  • /api/Trailer/Apply, /api/Trailer/Delete, /api/Trailer/GetList
  • /api/CargoOwnerDictionary/Apply, /api/CargoOwnerDictionary/Delete, /api/CargoOwnerDictionary/Get
  • /api/LegalPersons/Apply, /api/LegalPersons/Delete, /api/LegalPersons/GetList

Рекомендуемая частота синхронизации: не больше чем раз в 1 минуту.


2.2. Ограничения на удаление водителей, машин и прицепов

При удалении объектов-справочников (водителей, машин, прицепов) действуют бизнес-ограничения.

Система не позволяет удалить объект, если он используется в актуальных данных, например:

  • водитель назначен на активную или запланированную заявку;
  • машина участвует в активной заявке;
  • прицеп привязан к активной заявке или рейсу.

В этих случаях:

  • операция удаления завершается ошибкой (HTTP-статус 4xx);
  • в ответе возвращается текстовое пояснение причины, например что объект используется в заявке и не может быть удалён.

Рекомендуется при интеграции:

  • логировать текст ошибки;
  • отображать комментарий пользователю внешней системы;
  • при необходимости реализовать бизнес-процесс «вывода из эксплуатации» (деактивацию) вместо физического удаления.

2.3. Справочники, данные которых поступают из CARGO.RUN

  • Тип оплаты (PaymentType)
  • Тип НДС (NDSType)
  • Тип груза (CargoType)
  • Типы машин (CarType)
  • Типы прицепов (TrailerType)
  • Бренды машин (CarBrandType)
  • Бренды прицепов (TrailerBrandType)

Получение выполняется методом:

GET /api/catalogs/getSimple?$filter=externalId eq null&$orderby=id desc

Метод поддерживает OData-фильтры.


3. Использование справочников при создании заявок

Поля, заканчивающиеся на TypeId (например, paymentTypeId, ndsTypeId, typeId, brandTypeId) должны заполняться значениями из общих справочников.

Некорректные идентификаторы приведут к ошибке валидации.


4. Синхронизация заявок (Bid)

Заявка — основной объект интеграции.
Синхронизация выполняется по полю:

updatedAt

Существует два направления синхронизации:

  1. Внешняя система → CARGO.RUN
    (создание/обновление через /api/TruckingBids/Apply или /api/TruckingBids/Patch)

  2. CARGO.RUN → внешняя система
    (оперативные изменения через /api/tasks/queue, первичная загрузка и сверка через /api/bids/GetListForExternal)


5. Обработка updatedAt

Не используйте максимальный updatedAt последней страницы как единственный курсор: несколько заявок могут иметь одинаковую метку времени, а состав выборки меняется во время постраничного чтения.

Рекомендуемый алгоритм:

  1. До начала цикла зафиксировать верхнюю границу windowEnd в UTC.
  2. Взять нижнюю границу windowStart из состояния последней полностью успешной синхронизации и отступить назад на небольшой интервал перекрытия.
  3. Запросить фиксированное окно updatedAt ge windowStart and updatedAt le windowEnd с $orderby=updatedAt,id, $top=50 и последовательным $skip.
  4. Обработать все страницы; повторные записи безопасно обновлять по паре id и updatedAt. Учитывать записи с isDeleted = true.
  5. Только после успешной обработки всего окна атомарно сохранить windowEnd как новый завершённый рубеж.
  6. При ошибке не продвигать рубеж и повторить окно. Периодически выполнять контрольную сверку за более длинный период.

Перекрытие и дедупликация дают семантику «как минимум один раз», а не «ровно один раз». Документация API пока не определяет составной серверный курсор для записей с одинаковым updatedAt, поэтому обработчик должен быть идемпотентным.


6. Получение списка заявок из CARGO.RUN

Основной метод для инкрементальной синхронизации:

GET /api/bids/GetListForExternal

Пример запроса

/api/bids/GetListForExternal
?$filter=updatedAt ge 2024-01-23T21:00:00Z
        and updatedAt le 2024-01-25T20:59:59Z
        and createdAt ge 2022-09-30T21:00:00Z
&$top=50
&$orderby=updatedAt,id
&$skip=0

Запрос возвращает заявки:

  • обновлённые не раньше 24.01.2024 00:00 МСК (2024-01-23T21:00:00Z);
  • обновлённые не позже 25.01.2024 23:59:59 МСК (2024-01-25T20:59:59Z);
  • созданные после 01.10.2022 00:00 МСК (2022-09-30T21:00:00Z), если нужно ограничить выборку по дате создания;
  • первые 50 записей, начиная с позиции 0;
  • отсортированные по дате обновления и ID: updatedAt,id.

Все списки рекомендуется получать порциями по 50 записей. Не запрашивайте полный список без ограничения количества: тяжелые запросы увеличивают нагрузку на сервер и могут привести к временной блокировке пользователя системой.