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

Сценарий: заявка создаётся во внешней системе

Этот сценарий описывает процесс, в котором внешняя система (1С, ERP, WMS или другая учетная система) является источником создания заявок. CARGO.RUN принимает данные, формирует рейсы, управляет маршрутом, контролирует исполнение и возвращает статусы во внешнюю систему.


1. Общая последовательность процесса

Процесс включает следующие этапы:

  1. Внешняя система формирует заявку или заказ.
  2. Перед отправкой заявка проходит проверку данных.
  3. Внешняя система отправляет заявку в CARGO.RUN.
  4. CARGO.RUN создаёт заявку в статусе New (Черновик).
  5. Внешняя система запускает заявку в работу.
  6. CARGO.RUN планирует и исполняет рейс.
  7. Внешняя система регулярно получает обновления статусов заявки.

2. Требования к данным перед отправкой

Перед тем как создать заявку в CARGO.RUN, внешняя система должна убедиться:

  • все необходимые справочники синхронизированы:
  • контрагенты,
  • водители,
  • автомобили,
  • прицепы,
  • организации;

  • обязательные поля заполнены (см. раздел "Минимальные требования"):

  • cargoOwnerDictionaryItemId,
  • paymentTypeId,
  • ndsTypeId,
  • carId,
  • driverId,
  • bidPoints.

  • значения идентификаторов (xxxId) существуют в системе.

Если справочники не синхронизированы, система вернет ошибку валидации.


3. Создание заявки во внешней системе

Обычно внешняя система формирует заявку на основе внутренних процессов:

  • формирование груза,
  • данные клиента,
  • информация по отправителю/получателю,
  • планируемая дата доставки,
  • параметры перевозки.

После формирования заявки данные приводятся к структуре JSON, соответствующей требованиям API CARGO.RUN.


4. Создание черновика заявки в CARGO.RUN

Отправка выполняется запросом:

POST /api/TruckingBids/Apply
Content-Type: application/json
Authorization: Bearer <token>

Требование к адресу (геокодирование)

Для корректности адресов рекомендуется использовать геокодер CARGO.RUN:

POST /api/Map/GetAddresses

Тело запроса:

{
  "address": "<string>"
}

Метод возвращает структурированные данные: - координаты, - регион, - город, - район, - улицу и номер дома, - федеральный округ.

Рекомендуется всегда использовать результаты геокодера для bidPoints.geozone.


Пример создания черновика заявки

{
  "id": 0,
  "cargoOwnerDictionaryItemId": 10638021,
  "paymentTypeId": 41,
  "ndsTypeId": 40,
  "price": 234000,
  "cargos": [
    {
      "name": "ТНП",
      "typeId": 707,
      "extendedProperties": []
    }
  ],
  "typeOptions": [
    {
      "entityOptionId": 14655740,
      "id": 14655282
    }
  ],
  "bidPoints": [
    {
      "order": 0,
      "type": "LoadPoint",
      "planEnterDate": "2021-01-07T04:33:00",
      "geozone": {
        "location": {
          "type": "Point",
          "coordinates": [
            52.41153359413148,
            55.71049164294613
          ]
        },
        "address": "Россия, Республика Татарстан, Набережные Челны, Транспортный проезд, 15",
        "city": "Набережные Челны",
        "state": "Республика Татарстан",
        "county": "городской округ Набережные Челны",
        "street": "Транспортный проезд",
        "houseNumber": "15",
        "federalDistrict": "Приволжский федеральный округ",
        "radius": 0
      }
    },
    {
      "order": 1,
      "type": "UnloadPoint",
      "planEnterDate": "2021-01-07T13:33:00",
      "geozone": {
        "location": {
          "type": "Point",
          "coordinates": [
            48.39303731918335,
            54.30654645200388
          ]
        },
        "address": "Россия, Ульяновск, улица Минаева, 48Б",
        "city": "Ульяновск",
        "state": "Ульяновская область",
        "county": "городской округ Ульяновск",
        "street": "улица Минаева",
        "houseNumber": "48Б",
        "federalDistrict": "Приволжский федеральный округ",
        "radius": 0
      },
      "cargoOwnerDictionaryItemId": null
    }
  ],
  "driver": {
    "id": 16309296
  },
  "carOption": {
    "carId": 10483431
  },
  "trailerOption": {
    "trailerId": 17758587
  }
}

Важные детали

  • Поле id должно быть равно 0.
  • externalId можно использовать как атрибут для сопоставления, но он не уникален:
"externalId": "string"

После создания сохраните возвращённый id CARGO.RUN. Все обновления, смены статуса и удаления выполняйте по нему, а не по externalId.

Порожняя заявка

{
  "isEmptyMileageBid": true,
  "price": 1,
  "paymentTypeId": 41,
  "ndsTypeId": 40,
  "cargos": [
    {
      "id": 0,
      "name": null
    }
  ],
  "emptyMileageBid": {
    "logisticReasonTypeId": 12345,
    "technicalReason": null
  }
}

При порожней заявке:

  • price, paymentTypeId, ndsTypeId и непустой cargos передаются как технические заполнители для валидации; их значения при обработке порожней заявки игнорируются;
  • paymentTypeId и ndsTypeId должны ссылаться на существующие значения справочников;
  • контрагент cargoOwnerDictionaryItemId можно не указывать.

logisticReasonTypeId берётся из справочника причин порожнего пробега. Для технической порожней заявки вместо него передайте technicalReason (не более 256 символов). Эти два поля взаимоисключающие. Обязательность объекта emptyMileageBid зависит от настройки учёта причин в организации.


5. Запуск заявки в работу

После создания черновика необходимо запустить заявку:

POST /api/TruckingBids/SetStatus

Тело запроса:

{
  "bidId": 123456,
  "status": "Started"
}

Здесь 123456 — id, возвращённый при создании заявки. Значение 0 используется только при создании и не подходит для последующего изменения статуса.


6. Получение статусов и списка заявок во внешней системе

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

GET /api/bids/GetListForExternal

Метод возвращает HTTP-статус 200 и массив заявок.

Принцип работы синхронизации

У каждой заявки в CARGO.RUN есть поле:

updatedAt

Это дата последнего обновления заявки.
В процессе синхронизации используется следующий алгоритм:

  1. Внешняя система фиксирует верхнюю границу окна и запрашивает заявки, у которых updatedAt попадает в это окно.
  2. Все страницы окна обрабатываются идемпотентно по id и updatedAt.
  3. Верхняя граница сохраняется как новый рубеж только после успешной обработки всех страниц.
  4. Следующее окно начинается с небольшим перекрытием; дубликаты допустимы и отбрасываются.

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

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

<baseUrl>/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 (МСК)
    (23.01.2024 21:00:00 UTC);
  • с датой обновления меньше 25.01.2024 23:59 (МСК)
    (25.01.2024 20:59:59 UTC);
  • с датой создания больше 30.09.2022 (если необходимо ограничение по дате создания);
  • первые 50 заявок (параметр $top), начиная с 0 ($skip=0);
  • отсортированные по полю updatedAt.

7. Обработка ошибок и корректировка данных

Типовые причины ошибок при создании и обновлении заявок:

  • несоответствие идентификаторов справочников (водители, автомобили, прицепы, контрагенты);
  • некорректные адреса и геозоны;
  • некорректная структура массива bidPoints;
  • отсутствие обязательных полей.

Рекомендуется:

  • логировать все ошибки на стороне внешней системы;
  • отображать текст ошибки операторам;
  • повторять запрос после исправления данных.

8. Обновление заявки

Для обновления заявки поддерживаются два подхода.

8.1. Полное обновление заявки

Вызовите POST /api/TruckingBids/Apply и передайте полную актуальную модель заявки с её id > 0. Каждый вызов полностью перезаписывает заявку: отсутствующие значения могут быть потеряны или сброшены. Перед обновлением получите актуальную карточку и объедините изменения.

8.2. Частичное обновление заявки

Вызовите POST /api/TruckingBids/Patch. Для вложенных коллекций действуют особые правила: массив bidPoints передаётся целиком, даже при изменении одной точки. Подробности и ограничения приведены в справочнике методов заявок.