Отгрузка на основании заказа — стандартный сценарий продаж: клиент оформил заказ покупателя (customerorder), а вы формируете отгрузку (demand) с теми же позициями и связью между документами. В JSON API 1.2 это делается через шаблон new, который переносит организацию, контрагента, склад и товары из заказа автоматически.
Логика связи заказа и отгрузки
В МойСклад заказ покупателя (customerorder) — это намерение, а отгрузка (demand) — факт передачи товара со склада. Отгрузка «на основании» сохраняет ссылку на исходный заказ в поле customerOrder, благодаря чему в интерфейсе документы связаны, а отгруженное количество корректно учитывается в резервах и остатках.
Есть два пути создания отгрузки:
- Через шаблон
POST /entity/demand/new— сервис сам подставляет реквизиты и позиции из заказа; - Вручную — собрать тело demand целиком, указав
customerOrder,positionsи все реквизиты самостоятельно.
https://api.moysklad.ru/api/remap/1.2. Шаблонный путь предпочтителен: меньше ручной работы и ниже риск рассинхронизации реквизитов с заказом.Шаг 1. Получаем шаблон отгрузки
Шаблон запрашивается методом POST с телом, где указана meta заказа-основания:
POST /api/remap/1.2/entity/demand/new
{ "customerOrder": { "meta": { "href": "https://api.moysklad.ru/api/remap/1.2/entity/customerorder/{orderId}", "type": "customerorder", "mediaType": "application/json" } } }
В ответ придёт предзаполненный черновик отгрузки: организация (organization), контрагент (agent), склад (store), валюта, а также positions, перенесённые из заказа. Этот объект ещё не сохранён — его нужно отправить обратно.
/new лишь возвращает заготовку с корректными реквизитами. Пока вы не сделаете второй запрос POST, отгрузки в системе нет.Шаг 2. Создаём отгрузку
Полученный черновик (при необходимости отредактированный) отправляется обычным POST:
POST /api/remap/1.2/entity/demand
В тело кладётся объект из шаблона. Если реквизиты вас устраивают, достаточно передать минимум — organization, agent, store, customerOrder и positions:
{ "organization": {"meta": {...}}, "agent": {"meta": {...}}, "store": {"meta": {...}}, "customerOrder": {"meta": {...}}, "positions": [ {"quantity": 2, "price": 19990, "assortment": {"meta": {...}}} ] }
Ответ — созданная отгрузка с присвоенным id и номером. Связь с заказом уже установлена через customerOrder.
Частичная отгрузка и корректировка позиций
Часто отгружают не весь заказ, а часть. Шаблон переносит полное количество из заказа, поэтому позиции нужно скорректировать перед созданием:
- получите шаблон через
/demand/new; - в массиве
positionsуменьшитеquantityдо фактически отгружаемого; - лишние позиции удалите из массива;
- отправьте POST.
Оставшееся количество останется в заказе как неотгруженное, и позже можно создать вторую отгрузку на тот же customerOrder. МойСклад сам считает, сколько по заказу уже отгружено.
| Поле позиции | Назначение |
|---|---|
assortment | meta товара, модификации или услуги |
quantity | отгружаемое количество |
price | цена в копейках |
discount | скидка на позицию, % |
Проведение отгрузки и списание остатков
Списание товара со склада происходит только у проведённого документа. За это отвечает поле applicable: значение true означает, что отгрузка проведена и остатки уменьшены.
Провести можно сразу при создании, передав "applicable": true, либо позже через PUT /entity/demand/{id}. Непроведённая отгрузка (applicable: false) остаётся черновиком и на остатки не влияет.
Проверка связи и отгруженного количества
Чтобы убедиться, что отгрузка корректно связана с заказом, запросите заказ и разверните связанные документы:
GET /api/remap/1.2/entity/customerorder/{orderId}?expand=demands
В ответе появится массив demands со всеми отгрузками по этому заказу. Так удобно проверять полноту отгрузки в интеграции:
- суммируйте
quantityпо позициям всех отгрузок; - сравнивайте с
quantityпозиций заказа; - если совпало — заказ отгружен полностью, если нет — есть остаток.
Параметр expand экономит запросы: вместо отдельного чтения каждой отгрузки вы получаете связку одним обращением. Глубина expand ограничена — разворачивать бесконечную вложенность нельзя, поэтому для сложных связок стройте выборку в несколько уровней осознанно.
Если интеграция создаёт отгрузки автоматически, полезно логировать пару «id заказа → id отгрузки» на своей стороне. Так вы не будете каждый раз опрашивать expand=demands, а сразу узнаете, была ли уже отгрузка по заказу, и избежите повторного создания при обрыве связи. Это особенно важно при потоковой обработке заказов с сайта, где один и тот же заказ может прийти на обработку дважды.
Итог
Создание отгрузки на основании заказа — это два шага: получить шаблон POST /entity/demand/new с meta заказа и отправить готовый объект POST /entity/demand. Шаблон переносит реквизиты и позиции, частичную отгрузку задают корректировкой positions, а списание остатков включает applicable: true. Связь и полноту отгрузки проверяют через expand=demands.
Если этот сценарий нужно встроить в обмен между МойСклад, сайтом на 1С-Битрикс и CRM — чтобы заказ с сайта автоматически превращался в отгрузку с корректными остатками, — мы проектируем и разрабатываем такие интеграции. Настроим надёжный документооборот с обработкой частичных отгрузок и ошибок проведения.
Частые вопросы
Создаёт ли запрос /demand/new саму отгрузку?
Нет. Он лишь возвращает предзаполненный черновик с реквизитами и позициями заказа. Отгрузка появляется только после второго запроса POST /entity/demand.
Как установить связь отгрузки с заказом?
Через поле customerOrder с meta заказа-основания. При использовании шаблона /demand/new связь подставляется автоматически.
Как сделать частичную отгрузку?
Получите шаблон, уменьшите quantity в нужных позициях и удалите лишние из массива positions, затем отправьте POST. Остаток можно отгрузить позже второй отгрузкой.
Когда списываются остатки со склада?
Только когда отгрузка проведена, то есть поле applicable равно true. Непроведённый документ на остатки не влияет.
Можно ли создать несколько отгрузок по одному заказу?
Да. Все отгрузки ссылаются на один customerOrder, а МойСклад сам учитывает суммарно отгруженное количество по заказу.
Как проверить, полностью ли отгружен заказ?
Запросите заказ с expand=demands, просуммируйте количества по позициям всех отгрузок и сравните с количеством в заказе.
Что делать, если проведение упало из-за нехватки товара?
Это контроль отрицательных остатков по настройкам аккаунта. Обрабатывайте такую ошибку отдельно и не считайте отгрузку успешно созданной.
Обязательно ли использовать шаблон new?
Нет, отгрузку можно собрать вручную, указав customerOrder, positions и все реквизиты. Но шаблон снижает риск рассинхронизации реквизитов с заказом.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.