# API для работы с Грузами

:::caution
Методы версии v1.0 больше не поддерживаются и скоро будут полностью удалены.
Рекомендуем как можно быстрее перейти на актуальную версию API, чтобы избежать сбоев в работе интеграции.
:::

## Возможности API

API Грузов позволяет работам с [Грузами](https://help.ati.su/kak-dobavljat-i-redaktirovat-gruzy). С помощью API:

**Грузовладелец** может:

- [добавлять](https://ati.su/developers/raw/api/loads/published.md#post-public-v2-cargos), [обновлять](https://ati.su/developers/raw/api/loads/published.md#put-v1.0-loads-%7bloadId%7d-renew), [редактировать](https://ati.su/developers/raw/api/loads/published.md#put-public-v2-cargos-%7bcargoApplicationId%7d) и [удалять](https://ati.su/developers/raw/api/loads/published.md#delete-v1.0-loads-%7bloadId%7d) общедоступные грузы и грузы на Площадках;
- [настраивать приоритетный показ груза](https://ati.su/developers/raw/api/loads/published.md#put-v1.0-loads-%7bloadId%7d-priority);
- [получать встречные предложения по грузу](https://ati.su/developers/raw/api/loads/published.md#get-v1.0-loads-new-responses).

**Перевозчик** может:

- [узнавать о грузах компаний на Площадках (кроме Общей площадки ATI.SU)](https://ati.su/developers/raw/api/loads/published.md#get-v1.0-loads-search-byboards);
- [добавлять и редактировать встречные предложения](https://ati.su/developers/raw/api/loads/published.md#put-v1.0-loads-new-%7bloadId%7d-responses);
- [добавлять и редактировать комментарии к грузу](https://ati.su/developers/raw/api/loads/published.md#put-v1.0-loads-%7bloadId%7d-comments).

## Дубликаты и объединение грузов

При [добавлении](https://ati.su/developers/raw/api/loads/published.md#post-public-v2-cargos) или [редактировании](https://ati.su/developers/raw/api/loads/published.md#put-public-v2-cargos-%7bcargoApplicationId%7d) груза могут происходить конфликты, если в системе уже имеются похожие грузы.

### Дубликаты

У грузов совпадают все перечисленные параметры:

1. Одинаковые параметры CargoTypeId;
2. Одинаковые или отсутствующие параметры Weight, Volume, ADR;
3. Одинаковый или отсутствующий параметр PackType или различие у грузов только в то, что у load1= значение из словаря, у load2=0;
4. Одинаковые или отсутствующие параметра PalletCount, BeltCount или различие у грузов только в том, что у load1>0, у load2=0;
5. Одинаковые или отсутствующие параметры структуры Size;
6. Одинаковый параметр DogruzType;
7. Одинаковый или отсутствующий параметр SborGruz или различие только в этом параметре;
8. Одинаковые параметры Loading.CityId, Unloading.CityId;
9. Одинаковые параметры Loading.Street и Unloading.Street;
10. Любые списки дополнительных пунктов маршрута ExtraPoints;
11. Любое значение параметра Krugoreis;
12. Одинаковые или отсутствующие параметры Transport.CarType, LoadingType, UnloadingType или различие у грузов только в том, что значение load1>load2;
13. Одинаковые или отсутствующие параметры Stsepka, Pnevmohod, Koniki, TIR, CMR, T1, SanPassport или различие у грузов только в том, что значение у load1=true, у load2=false;
14. Любой параметр TrucksQuantity;
15. Одинаковые параметры DateType, а так же если совпадает FirstDate при разных значениях DateType;
16. Одинаковые или отсутствующие параметры TimeStart, TimeEnd, или различие у грузов только в то, что значение load1>load2;
17. Одинаковый или отсутствующий параметр Note;
18. Одинаковые параметры ставки Payment.RateSum, Payment.SumWithNDS, Payment.SumWithoutNDS и Payment.CurrencyID. Если различие у грузов только в значении перечисленных полей, груз будет дубликатом;
19. Одинаковые параметры оплаты Torg, PrepayPercentEnabled, InFuel, DirectContract, OnUnloading, PayDaysEnabled или различие у грузов только в то, что значение у load1=true, у load2= false;
20. Любой параметр AcceptPaymentTypes в параметре "Запрос ставки";
21. Любой параметр структуры LoadFile и любой параметр OrderNumber.

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

- load1 и load2 отличаются только тем, что у груза load2 нет сцепки - ошибка дубликата груза
- load1 и load2 отличаются только размером ставки - ошибка дубликата груза
- load1 и load2 отличаются размером ставки и городом загрузки - добавится новый груз
- load1 и load2 отличаются только городом загрузки - добавится новый груз

Если груз оказался дубликатом, то новый груз не добавится и будет отправлена ошибка 409 Conflict.

```json
{
  "Error": "load_conflict_error",
  "Reason": "Найден дубликат в грузах",
  "ConflictLoadId": "e87584af-1bed-457b-9ee3-a595b715c550"
}
```

### Объединение

Объединение происходит, если в системе уже имеется груз load1, который отличается от load2, одним или несколькими из перечисленных параметров:

1. Параметр PackType у load1 = 0, у load2 = значение из словаря;
2. Параметры PalletCount, BeltCount у load1 ≥ 0, у load2 > 0;
3. Параметры Transport.CarType, LoadingType, UnloadingType load1 < load2;
4. Параметры Stsepka, Pnevmohod, Koniki, TIR, CMR, T1, SanPassport у load1 = false, у load2 = true;
5. Параметры TimeStart, TimeEnd load1 < load2;
6. Параметры Torg, PrepayPercentEnabled, InFuel, DirectContract, OnUnloading, PayDaysEnabled у load1 = false, у load2 = true.

#### Эффект при объединении

Новый груз не добавляется, а редактируется уже имеющийся. Например, уже имеющийся груз получает CarType от обоих грузов.

После объединения грузов будет отправлено сообщение с кодом ответа сервера 202, содержащее json с обновленным грузом.

## Пользовательские ошибки в API грузов

В API грузов может произойти достаточно много пользовательских ошибок, и для идентификации конкретной ошибки не всегда достаточно http кода ошибки. Поэтому при возникновении ошибки в теле ответа всегда будет присутствовать объект ошибки, содержащий 2 поля: `Error` с кодом ошибки в виде строки и `Reason` с пояснением. В групповых операциях поля `Error` и `Reason` будут указаны для каждого груза, с которым произошла ошибка во время выполнения операции.

### Примеры ошибок

#### Ошибка при одиночной операции (на примере добавления груза)

```json
{
  "Error": "load_conflict_error",
  "Reason": "Найден дубликат в грузах",
  "ConflictLoadId": "271be1d2-2a91-e611-a37f-005056c00008"
}
```

#### Ошибка при групповой операции (на примере группового восстановления)

```json
{
  "0e9050e4-f5cb-4835-acb2-c211151bad64": {
    "Status": 2,
    "Message": "Груз был помещен в архив менее 60 минут назад",
    "Error": "load_archive_delay_not_elapsed",
    "Reason": "Груз был помещен в архив менее 60 минут назад"
  },
  "9b380991-433f-4738-a68d-8b851c1b5472": {
    "Status": 0,
    "Message": "Успешная операция"
  }
}
```

#### Ошибка валидации(на примере добавления груза)

В случае ошибки валидации json в теле запроса возникает ошибка _json_validation_error_. В теле ответа будут поля `Error` и `Reason`, и, кроме того, поле `ErrorList`, содержащее массив объектов вида `{property;reason}`, где:  
 `property` – название поля, в котором произошла ошибка;  
 `reason` – причина ошибки.

```json
{
  "Error": "json_validation_error",
  "Reason": "Ошибка валидации json",
  "ErrorsList": [
    {
      "property": "Cargo.Weight",
      "reason": "Максимальная длина для параметра вес - 4 символа",
      "error": "length_out_of_range",
      "context": {
        "Min": 0,
        "Max": 4
      }
    },
    {
      "property": "FirstDate",
      "reason": "Если значение параметра DateType равно 0 или 2, допустимое значение параметра FirstDate - текущая дата",
      "error": "must_be_current_date"
    },
    {
      "property": "LastDate",
      "reason": "Параметр LastDate должен быть больше либо равен параметру FirstDate",
      "error": "must_be_greater_or_equal_than",
      "context": {
        "Min": "2021-06-16T12:00:00.51"
      }
    }
  ]
}
```

#### Ошибка доступа (на примере добавления груза)

```json
{
  "Error": "access_denied_error",
  "Reason": "У вашего контакта нет доступа для работы с одной или несколькими персональными площадками, указанными в грузе",
  "AccessDeniedReason": 13,
  "ExceededLimit": null
}
```

### Список возможных 4хх ошибок

| **Код ошибки**                     | **Пояснение**                                                                                                            |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| deserialization_error              | Ошибка десериализации json                                                                                               |
| json_validation_error              | Ошибка валидации json из тела запроса                                                                                    |
| validation_error                   | Ошибка валидации. Возникает в случае любой ошибки валидации, кроме ошибки валидации тела запроса (json_validation_error) |
| load_conflict_error                | Найден дубликат в грузах                                                                                                 |
| load_archive_delay_not_elapsed     | Груз был помещен в архив менее 60 минут назад                                                                            |
| load_renew_delay_not_elapsed       | Груз был обновлен менее 60 минут назад                                                                                   |
| boards_access_denied_error         | Некоторые из указанных площадок не существуют или вы не имеете доступа к ним                                             |
| access_denied_error                | Отказано в доступе                                                                                                       |
| account_not_found_error            | Фирма не найдена                                                                                                         |
| contact_not_found_or_deleted       | Первый контакт не существует или удален                                                                                  |
| unavailable_contact_selected       | В качестве первого контакта должен быть указан контакт из доступного подразделения                                       |
| city_not_found_error               | Город не найден                                                                                                          |
| comment_not_found_error            | Комментарий для груза не найден                                                                                          |
| dictionary_element_not_found_error | Элемент словаря не найден                                                                                                |
| load_not_found_error               | Груз не найден                                                                                                           |
| response_not_found_error           | Отзыв на груз не найден                                                                                                  |
| avatar_not_found_error             | Аватар не найден                                                                                                         |
| load_reserved_error                | Груз зарезервирован/взят, операции с грузом запрещены                                                                    |
| load_cant_reserve                  | Невозможно зарезервировать груз. Груз уже зарезервирован, либо не поддерживает резервирование                            |
