Создает инвентаризацию материалов или продуктов на складе. Передавайте только фактические остатки: ожидаемые Controlata рассчитает сама на дату инвентаризации.

```
v1/audits/add.php
```

## Параметры

| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| storage_id | int | Да | Склад, на котором проводится инвентаризация |
| materials | array | materials или products | Строки инвентаризации материалов |
| products | array | materials или products | Строки инвентаризации продуктов |
| date | string | Нет | Дата инвентаризации, YYYY-MM-DD. По умолчанию сегодня |

Строка materials и products:

| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | int | id или sku | ID материала или продукта |
| sku | string | id или sku | Артикул |
| actual | float | Да | Фактический остаток, 0 или больше |
| notes | string | Нет | Заметки к строке |

Передайте строки только в одном массиве: инвентаризация считает либо материалы, либо продукты. Каждая позиция указывается один раз. Как указывать позицию по id или артикулу, описано в статье [Общие правила](https://developers.controlata.ru/hc/api-docs/articles/rules).

## Как работает

* **Ожидаемый остаток** каждой строки рассчитывается на дату инвентаризации включительно по проведенным операциям склада (см. [Инвентаризации](https://developers.controlata.ru/hc/api-docs/articles/audits)).
* **Корректировка.** Разница между actual и ожидаемым остатком добавляется на склад (излишек) или списывается по FIFO (недостача). Строка без разницы остаток не меняет.
* **Статус** берется из настройки **Статус новой инвентаризации по умолчанию**. В статусе **Проведена** остатки корректируются сразу, в статусе **План** корректировка только планируется.
* **Номер** присваивается автоматически, задать его нельзя.
* В инвентаризацию попадают только переданные позиции. Остальные позиции склада она не затрагивает.

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

```
{
    "storage_id": 3998,
    "date": "2026-09-30",
    "materials": [
        {
            "id": 2051,
            "actual": 3.8
        },
        {
            "sku": "M022",
            "actual": 0,
            "notes": "Не найдено на складе"
        }
    ]
}
```

## Пример ответа

```
{
    "success": true,
    "audit_id": 1699,
    "num": 24,
    "status": 1
}
```

В ответе приходят ID, номер и код статуса новой инвентаризации. Ожидаемые остатки и разницу по строкам возвращает [v1/audits/get_entry](https://developers.controlata.ru/hc/api-docs/articles/audits-get-entry).

## Ошибки

| Ошибка | Причина |
|---|---|
| No storage_id in input | Не передан storage_id |
| Storage ID is not set | storage_id равен 0 или пустой |
| Storage ID not found | Склад не найден или удален |
| An audit counts either materials or products. Create separate audits | Переданы и materials, и products |
| No products or materials in input | Не передано ни одной строки |
| Materials is not an array | materials не массив (так же для products) |
| Line 0 of materials must be an object | Строка не объект (вместо 0 будет номер строки) |
| SKU or id not set for material 0 | В строке нет ни id, ни sku |
| Material with id 2051 not found | Материал не найден или удален (для артикула: Material with SKU "M022" not found) |
| Actual must be 0 or greater for material with id 2051 | actual не передан, не число или меньше 0 |
| Material with id 2051 is listed twice | Позиция указана в двух строках |
| Date is not a valid date in format YYYY-MM-DD | Неверный формат даты |
