Бөлісу құралы:


Общедоступные API видимости запасов

Примечание

Вместо Azure Active Directory теперь используется Microsoft Entra ID. Подробнее

В этой статье описываются открытые API, предоставляемые видимостью запасов.

Открытый интерфейс REST API надстройки контроля запасов представляет несколько определенных конечных точек интеграции. Он поддерживает четыре основных типа взаимодействий:

  • Разноска изменений запасов в наличии в надстройку из внешней системы
  • Настройка или переопределение количества запасов в наличии в надстройке из внешней системы
  • Разноска событий резервирования в надстройку из внешней системы
  • Запрос текущих количеств в наличии из внешней системы

В следующей таблице перечислены API, которые сейчас доступны:

Путь Метод Описание
/api/environment/{environmentId}/onhand Опубликовать Создание одного события изменения в наличии
/api/environment/{environmentId}/onhand/bulk Опубликовать Создание нескольких событий изменения
/api/environment/{environmentId}/setonhand/{inventorySystem}/bulk Опубликовать Настройка/переопределение количеств в наличии
/api/environment/{environmentId}/onhand/reserve Опубликовать Создание одного события предварительного резервирования
/api/environment/{environmentId}/onhand/reserve/bulk Опубликовать Создание нескольких событий предварительного резервирования
/api/environment/{environmentId}/onhand/unreserve Опубликовать Реверсирование одного события предварительного резервирования
/api/environment/{environmentId}/onhand/unreserve/bulk Опубликовать Реверсирование нескольких событий предварительного резервирования
/api/environment/{environmentId}/onhand/reserve/resyncjob Опубликовать Очистка данных резервирования
/api/environment/{environmentId}/onhand/changeschedule Опубликовать Создание одного запланированного изменения запасов в наличии
/api/environment/{environmentId}/onhand/changeschedule/bulk Опубликовать Создание нескольких изменений запасов в наличии с датами
/api/environment/{environmentId}/onhand/indexquery Опубликовать Запрос с использованием метода POST (рекомендуется)
/api/environment/{environmentId}/onhand Получить Запрос с использованием метода GET
/api/environment/{environmentId}/onhand/exactquery Опубликовать Извлечение запроса с использованием метода POST
/api/environment/{environmentId}/allocation/allocate Опубликовать Создание одного события распределения
/api/environment/{environmentId}/allocation/unallocate Опубликовать Создание одного события нераспределения
/api/environment/{environmentId}/allocation/reallocate Опубликовать Создание одного события перераспределения
/api/environment/{environmentId}/allocation/consume Опубликовать Создание одного события потребления
/api/environment/{environmentId}/allocation/query Опубликовать Запрос результата распределения
/api/environment/{environmentId}/onhand/productsearch/indexquery Опубликовать Отправка индексного запроса с поиском продуктов
/api/environment/{environmentId}/onhand/productsearch/exactquery Опубликовать Отправка точного запроса с поиском продуктов

Примечание

Частью пути {environmentId} является идентификатор среды в Microsoft Dynamics Lifecycle Services.

Массовый API-интерфейс может возвращать максимум 512 записей для каждого запроса.

Аутентификация

Маркер безопасности платформы используется для вызова открытых API видимости запасов. Таким образом, необходимо создать токен Microsoft Entra с помощью приложения Microsoft Entra. Затем необходимо использовать маркер Microsoft Entra, чтобы получить маркер доступа из службы безопасности.

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

  1. Выполните вход на портал Azure и используйте его, чтобы найти значения clientId и clientSecret для вашего приложения Dynamics 365 Supply Chain Management.

  2. Получите токен Microsoft Entra (aadToken), отправив HTTP-запрос со следующими свойствами:

    • URL-адрес:https://login.microsoftonline.com/${aadTenantId}/oauth2/v2.0/token

    • Метод:GET

    • Содержимое основной части (данные формы):

      Ключ значение
      client_id ${aadAppId}
      client_secret ${aadAppSecret}
      grant_type client_credentials
      область 0cdb527f-a8d1-4bf8-9436-b352c68682b2/.default

    В ответе должен быть получен токен Microsoft Entra (aadToken). Она должна быть похожа на следующий пример.

    {
        "token_type": "Bearer",
        "expires_in": "3599",
        "ext_expires_in": "3599",
        "access_token": "eyJ0eX...8WQ"
    }
    
  3. Сформулируйте запрос в формате JavaScript (JSON), который напоминает следующий пример.

    {
        "grant_type": "client_credentials",
        "client_assertion_type": "aad_app",
        "client_assertion": "{Your_Microsoft EntraToken}",
        "scope": "https://inventoryservice.operations365.dynamics.com/.default",
        "context": "{$LCS_environment_id}",
        "context_type": "finops-env"
    }
    

    Обратите внимание на следующие аспекты:

    • Значение client_assertion должно быть токеном Microsoft Entra (aadToken), полученным на предыдущем шаге.
    • Значение context должно быть идентификатором среды Lifecycle Services, в которой требуется развернуть надстройку.
    • Установите все остальные значения, как показано в примере.
  4. Получите токен доступа (access_token), отправив HTTP-запрос со следующими свойствами:

    • URL-адрес:https://securityservice.operations365.dynamics.com/token
    • Метод:POST
    • Заголовок HTTP: включите версию API. (Ключ — Api-Version, и значение — 1.0.)
    • Основное содержимое — включает запрос JSON, созданный на предыдущем шаге.

    В ответе должен быть получен маркер доступа (access_token). Следует использовать этот маркер в качестве маркера носителя для вызова API видимости запасов. Рассмотрим пример.

    {
        "access_token": "{Returned_Token}",
        "token_type": "bearer",
        "expires_in": 3600
    }
    

Примечание

URL-адрес https://securityservice.operations365.dynamics.com/token представляет собой общий URL-адре службы безопасности. При вызове URL-адреса первый отклик представляет собой перенаправление HTTP с кодом состояния307 в заголовках отклика и запись с ключом Location, которая содержит целевой URL-адрес службы безопасности. Этот URL-адрес имеет следующий формат: https://gw.{$geo}-il101.gateway.prod.island.powerapps.com/securityservice/token. Например, если среда находится в геообъекте "США", URL-адрес может быть следующим: https://gw.us-il101.gateway.prod.island.powerapps.com/securityservice/token. Если код состояния отклика 307 для вас неприемлем, можно вручную создать URL-адрес, соответствующий расположению вашей среды FinOps. Самый простой способ — это открыть https://gw.as-il101.gateway.prod.island.powerapps.com/securityservice/token в браузере и затем скопировать адрес в адресной строке.

Создание событий изменения в наличии

Существуют два интерфейса API для создания событий изменения в наличии:

  • Создать одну запись: /api/environment/{environmentId}/onhand
  • Создание нескольких записей: /api/environment/{environmentId}/onhand/bulk

В следующей таблице дана сводка значение каждого поля в тексте JSON.

FieldID Описание
id Уникальный код для конкретного события изменения. Если из-за сбои системы происходит повторная отправка, этот код используется, чтобы гарантировать, что одно и то же событие не будет дважды учитываться в системе.
organizationId Идентификатор организации, связанной с событием. Это значение сопоставляется с организацией или идентификатором области данных в Supply Chain Management.
productId Идентификатор продукта.
quantities Это количество, на которое должно быть уменьшено количество в наличии. Например, если на полку добавлено 10 новых книг, это значение будет равно quantities:{ shelf:{ received: 10 }}. Если с полки убраны или проданы три книги, это значение будет равно quantities:{ shelf:{ sold: 3 }}.
dimensionDataSource Источник данных для аналитик, используемых в разноске события изменения и запроса. Если указан источник данных, можно использовать настраиваемые аналитики из указанного источника данных. С помощью конфигурации аналитик видимость запасов может сопоставлять пользовательские аналитики с общими аналитиками по умолчанию. Если значение dimensionDataSource не указано, в запросах могут использоваться только универсальные базовые аналитики.
dimensions Динамическая пара "ключ-значение". Значения сопоставляются с некоторыми аналитиками в Supply Chain Management. Однако можно также добавить пользовательские аналитики (например, Источник), чтобы указать, поступает ли событие из модуля Supply Chain Management или из внешней системы.

Примечание

Если для правила разделения данных задано значение По коду продукта, то siteId и locationId являются необязательными аналитиками. В противном случае они являются обязательными аналитиками. Это правило также применяется к API распределения, предварительного резервирования и изменения расписания.

В следующих подразделах приводятся примеры, демонстрирующие использование этих интерфейсов API.

Создание одного события изменения в наличии

Этот API создает одно событие изменения в наличии.

Path:
    /api/environment/{environmentId}/onhand
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        id: string,
        organizationId: string,
        productId: string,
        dimensionDataSource: string, # Optional
        dimensions: {
            [key:string]: string,
        },
        quantities: {
            [dataSourceName:string]: {
                [key:string]: number,
            },
        },
    }

В следующем примере показано содержимое текста примера. В этом примере компания имеет систему POS-терминалов, которая обрабатывает проводки в магазине и, соответственно, изменения запасов. Клиент вернул в магазин красную футболку. Чтобы отразить это изменение, вы разносите одно событие изменения для продукта Футболка. Это событие увеличит количество продукта Футболка на 1.

{
    "id": "Test201",
    "organizationId": "usmf",
    "productId": "T-shirt",
    "dimensionDataSource": "pos",
    "dimensions": {
        "siteId": "1",
        "locationId": "11",
        "posMachineId": "0001",
        "colorId": "red"
    },
    "quantities": {
        "pos": {
            "inbound": 1
        }
    }
}

В следующем примере показано содержимое текста примера без dimensionDataSource. В этом случае dimensions будет базовой аналитикой. Если dimensionDataSource установлен, то dimensions могут быть либо аналитиками источника данных, либо базовыми аналитиками.

{
    "id": "Test202",
    "organizationId": "usmf",
    "productId": "T-shirt",
    "dimensions": {
        "siteId": "1",
        "locationId": "11",
        "colorId": "red"
    },
    "quantities": {
        "pos": {
            "inbound": 1
        }
    }
}

Создание нескольких событий изменения

Этот интерфейс API может создавать события изменения, подобно тому, как может API одного события. Единственное различие состоит в том, что этот API может создавать несколько записей одновременно. Таким образом, значения Path и Body различаются. Для этого API Body предоставляет массив записей. Максимальное число записей: 512. Таким образом, API массового изменения запасов в наличии может поддерживать до 512 событий изменения за раз.

Например, компьютер POS-терминала в розничном магазине обработал следующие две проводки:

  • Один заказ на возврат одной красной футболки
  • Одна проводка на продажу трех черных футболок

В этом случае можно включить оба обновления запасов в один вызов API.

Path:
    /api/environment/{environmentId}/onhand/bulk
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    [
        {
            id: string,
            organizationId: string,
            productId: string,
            dimensionDataSource: string, # Optional
            dimensions: {
                [key:string]: string,
            },
            quantities: {
                [dataSourceName:string]: {
                    [key:string]: number,
                },
            },
        },
        ...
    ]

В следующем примере показано содержимое текста примера.

[
    {
        "id": "Test203",
        "organizationId": "usmf",
        "productId": "T-shirt",
        "dimensionDataSource": "pos",
        "dimensions": {
            "SiteId": "Site1",
            "LocationId": "11",
            "posMachineId": "0001"
            "colorId": "red"
        },
        "quantities": {
            "pos": { "inbound": 1 }
        }
    },
    {
        "id": "Test204",
        "organizationId": "usmf",
        "productId": "T-shirt",
        "dimensions": {
            "siteId": "1",
            "locationId": "11",
            "colorId": "black"
        },
        "quantities": {
            "pos": { "outbound": 3 }
        }
    }
]

Настройка/переопределение количеств в наличии

API Задано в наличии переопределяет текущие данные для указанного продукта. Эта функция обычно используется для обновления инвентаризации запасов. Например, в ходе ежедневной инвентаризации запасов магазин может обнаружить фактическое количество запасов в наличии для красной футболки равно 100. Таким образом, входящее количество в POS-терминале должно быть обновлено до 100, независимо от того, какое было предыдущее количество. Этот API можно использовать для переопределения существующего значения.

Path:
    /api/environment/{environmentId}/setonhand/{inventorySystem}/bulk
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    [
        {
            id: string,
            organizationId: string,
            productId: string,
            dimensionDataSource: string, # Optional
            dimensions: {
                [key:string]: string,
            },
            quantities: {
                [dataSourceName:string]: {
                    [key:string]: number,
                },
            },
            modifiedDateTimeUTC: datetime,
        },
        ...
    ]

В следующем примере показано содержимое текста примера. Поведение этого API отличается от поведения интерфейсов API, описанных в разделе Создание событий изменения в наличии ранее в этой статье. В этом примере количество продукта Футболка будет задано как 1.

[
    {
        "id": "Test204",
        "organizationId": "usmf",
        "productId": "T-shirt",
        "dimensionDataSource": "pos",
        "dimensions": {
            "SiteId": "1",
            "LocationId": "11",
            "posMachineId": "0001"
            "colorId": "red"
        },
        "quantities": {
            "pos": {
                "inbound": 100
            }
        }
    }
]

Создание событий резервирования

Для использования API Резервирование необходимо включить функцию резервирования и выполнить настройку резервирования. Дополнительные сведения (включая поток данных и образец сценария) см. в разделе Резервирования в видимости запасов.

Создание одного события резервирования

Можно выполнить резервирование для других параметров источника данных. Чтобы настроить этот тип резервирования, сначала укажите источник данных в параметре dimensionDataSource. Затем в параметре dimensions задайте аналитики в соответствии с параметрами аналитик в целевом источнике данных.

При вызове API резервирования можно контролировать проверку резервирования путем указания логического параметра ifCheckAvailForReserv в тексте запроса. Значение True означает, что проверка является обязательной, а значение False означает, что проверка не является обязательной. Значение по умолчанию — True.

Если необходимо реверсировать резервирование или отказаться от указанного количества запасов, установите отрицательное значение количества и задайте для параметра ifCheckAvailForReserv значение False для пропуска проверки. Также имеется выделенный API-интерфейс отмены резервирования для выполнения той же задачи. Разница заключается только в способе вызова двух интерфейсов API. Конкретное событие резервирования проще реверсировать, используя reservationId с API-интерфейсом отмены резервирования. Дополнительные сведения см. в разделе Отмена резервирования одного события резервирования.

Path:
    /api/environment/{environmentId}/onhand/reserve
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        id: string,
        organizationId: string,
        productId: string,
        dimensionDataSource: string,
        dimensions: {
            [key:string]: string,
        },
        quantityDataSource: string, # optional
        quantities: {
            [dataSourceName:string]: {
                [key:string]: number,
            },
        },
        modifier: string,
        quantity: number,
        ifCheckAvailForReserv: boolean,
    }

В следующем примере показано содержимое текста примера.

{
    "id": "reserve-0",
    "organizationId": "SCM_IV",
    "productId": "iv_contoso_product",
    "quantity": 1,
    "quantityDataSource": "iv",
    "modifier": "softReservOrdered",
    "ifCheckAvailForReserv": true,
    "dimensions": {
        "siteId": "iv_contoso_site",
        "locationId": "iv_contoso_location",
        "colorId": "red",
        "sizeId": "small"
    }
}

В следующем примере показан успешный ответ.

{
    "reservationId": "RESERVATION_ID",
    "id": "ohre~id-822-232959-524",
    "processingStatus": "success",
    "message": "",
    "statusCode": 200
}

Создание нескольких событий резервирования

Этот интерфейс API представляет собой массовую версию API одного события.

Path:
    /api/environment/{environmentId}/onhand/reserve/bulk
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    [
        {
            id: string,
            organizationId: string,
            productId: string,
            dimensionDataSource: string,
            dimensions: {
                [key:string]: string,
            },
            quantityDataSource: string, # optional
            quantities: {
                [dataSourceName:string]: {
                    [key:string]: number,
                },
            },
            modifier: string,
            quantity: number,
            ifCheckAvailForReserv: boolean,
        },
        ...
    ]

Реверсирование событий резервирования

API-интерфейс Отмена резервирования выступает в качестве обратной операции для событий Резервирование. Он предоставляет способ сторнирования события резервирования, указанного по reservationId, или для уменьшения количества резервирования.

Реверсирование одного события резервирования

Когда создается резервирование, reservationId будет включен в тело ответа. Для отмены резервирования необходимо указать то же самое значение reservationId, и включить те же значения organizationId, productId и dimensions, которые использовались для вызова API-интерфейса резервирования. Наконец, укажите значение OffsetQty, представляющее число номенклатур, которое должно быть освобождено из предыдущего резервирования. Резервирование может быть полностью или частично отменено в зависимости от указанного значения OffsetQty. Например, если 100 единиц номенклатуры было зарезервировано, можно указать OffsetQty: 10, чтобы отменить резервирование 10 из первоначально зарезервированной суммы.

Path:
    /api/environment/{environmentId}/onhand/unreserve
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        id: string,
        organizationId: string,
        productId: string,
        reservationId: string,
        dimensions: {
            [key:string]: string,
        },
        OffsetQty: number
    }

В следующем коде показан пример содержимого текста.

{
    "id": "unreserve-0",
    "organizationId": "SCM_IV",
    "productId": "iv_contoso_product",
    "reservationId": "RESERVATION_ID",
    "dimensions": {
        "siteid":"iv_contoso_site",
        "locationid":"iv_contoso_location",
        "ColorId": "red",
        "SizeId": "small"
    },
    "OffsetQty": 1
}

В следующем коде показан пример текста успешного ответа.

{
    "reservationId": "RESERVATION_ID",
    "totalInvalidOffsetQtyByReservId": 0,
    "id": "ohoe~id-823-11744-883",
    "processingStatus": "success",
    "message": "",
    "statusCode": 200
}

Примечание

Когда в тексте ответа значение OffsetQty меньше или равно количеству резервирования, processingStatus будет "success" и totalInvalidOffsetQtyByReservId будет равно 0.

Если OffsetQty больше зарезервированной суммы, processingStatus будет "partialSuccess" и totalInvalidOffsetQtyByReservId будет разницей между OffsetQty и зарезервированным количеством.

Например, если резервирование имеет количество 10, а OffsetQty равно 12, totalInvalidOffsetQtyByReservId будет 2.

Реверсирование нескольких событий резервирования

Этот интерфейс API представляет собой массовую версию API одного события.

Path:
    /api/environment/{environmentId}/onhand/unreserve/bulk
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    [      
        {
            id: string,
            organizationId: string,
            productId: string,
            reservationId: string,
            dimensions: {
                [key:string]: string,
            },
            OffsetQty: number
        }
        ...
    ]

Очистка данных резервирования

API очистка данных резервирования используется для очистки исторических данных резервирования. Тело должно представлять собой список источников данных. Если список пуст, все источники данных будут очищены.

Path:
    /api/environment/{environmentId}/onhand/reserve/resyncjob
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    [      
        "iv",
        "pos"
    ]

Запрос в наличии

Используйте API Запрос в наличии для получения текущих данных запасов в наличии для вашей продукции. Этот интерфейс API можно использовать, если необходимо знать запасы на складе, например, когда необходимо просмотреть уровни складских запасов продукта на веб-сайте электронной коммерции или если требуется проверить доступность продукта по регионам или в ближайших магазинах и на ближайших складах. В настоящее время API поддерживает запросы до 5000 отдельных номенклатур по значению productID. В каждом запросе также может быть указано несколько значений siteID и locationID. Если для правила разделения данных задано значение По местоположению, максимальный предел определяется следующей формулой:

NumOf(SiteID) × NumOf(LocationID) <= 10000.

Запрос с использованием метода POST

Запрос по API записи доступен в двух версиях. В следующей таблице описаны различия.

API версии 1.0 API версии 2.0
Может запросить только один код организации. Может запрашивать несколько кодов организации.
Может запрашивать до 10 000 комбинаций объектов и складов. Может запросить более 10 000 комбинаций кодов организации, объектов и складов. Может возвращать результаты на нескольких страницах.

В следующих подразделах показано, как использовать каждую версию API.

Запрос по post API версии 1.0

Path:
    /api/environment/{environmentId}/onhand/indexquery
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        dimensionDataSource: string, # Optional
        filters: {
            organizationId: string[],
            productId: string[],
            siteId: string[],
            locationId: string[],
            [dimensionKey:string]: string[],
        },
        groupByValues: string[],
        returnNegative: boolean,
    }

В основной части этого запроса dimensionDataSource является необязательным параметром. Если оно не задано, filters будет рассматриваться как Базовая аналитика.

Этот параметр returnNegative определяет, содержат ли результаты отрицательные значения.

Данные запроса, хранимые по местоположению

Этот раздел применяется, когда для правила разделения данных задано значение По местоположению.

  • organizationId должен быть массивом, содержащим точно одно значение.
  • productId может содержать одно или несколько значений. Если это пустой массив, система вернет все товары для указанных сайтов и местоположений. В этом случае, siteId и locationId не должны быть пустыми.
  • siteId и locationId используются для создания разделов. Вы можете указать более одного значения siteId и locationId в запросе Запрос в наличии. Если оба массива пусты, система вернет все сайты и местоположения для указанных продуктов. В этом случае productId не должен быть пустым.

Мы рекомендуем использовать параметр groupByValues таким образом, чтобы это соответствовало вашей конфигурации индекса. Дополнительные сведения см. в Конфигурация индексов продуктов в наличии.

Данные запросов, хранимые по кодам продуктов

Этот раздел применяется, когда для правила разделения данных задано значение По коду продукта. В этом случае обязательны два filters поля: organizationId, productId.

  • organizationId должен быть массивом, содержащим точно одно значение.
  • productId должен быть массивом с минимум одним значением.

В отличие от хранения данных по местоположению, если вы не укажите значения для siteId или locationId, складская информация для каждого кода продукта будет агрегироваться по всем объектам и/или местоположениям.

Примечание

Если вы включили функции графика изменения запасов в наличии и количеств, доступных для заказа (ATP), запрос также может включать логический параметр QueryATP, который управляет тем, содержат ли результаты запроса сведения ATP. Дополнительные сведения и примеры см. в разделе Графики изменения запасов в наличии и доступность для заказа.

В следующем примере показано содержимое текста примера. Он показывает, что можно запросить запасы в наличии из нескольких местоположений (складов).

{
    "dimensionDataSource": "pos",
    "filters": {
        "organizationId": ["usmf"],
        "productId": ["T-shirt"],
        "siteId": ["1"],
        "locationId": ["11","12","13"],
        "colorId": ["red"]
    },
    "groupByValues": ["colorId", "sizeId"],
    "returnNegative": true
}

В следующем примере показано, как запросить все продукты на конкретном сайте и в местонахождении.

{
    "filters": {
        "organizationId": ["usmf"],
        "productId": [],
        "siteId": ["1"],
        "locationId": ["11"],
    },
    "groupByValues": ["colorId", "sizeId"],
    "returnNegative": true
}

Запрос по post API версии 2.0

Path:
    /api/environment/{environmentId}/onhand/indexquery?pageNumber={pageNumber}&pageSize={pageSize}
Method:
    Post
Headers:
    Api-Version="2.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    # Same as version 1.0

Формат запроса на API версии 2.0 аналогичен формату для версии 1.0, но также поддерживаются два дополнительных параметра: pageNumber и pageSize, которые позволяют системе разбить один большой результат на несколько более мелких документов. Результаты сортируются по складам (locationId), а параметры используются для разделения результатов на страницы:

  • pageSize устанавливает количество складов (locationId значений), возвращаемых на каждой странице.
  • pageNumber устанавливает номер возвращенной страницы.

Запрос этого формата возвращает данные о запасах в наличии, начиная с номера склада({pageNumber} - 1), × {pageSize} и включает данные для следующих {pageSize} складов.

API версии 2.0 отвечает документом, использующий следующую структуру:

{
    Value: { # Response same as Api-Version=1.0 }
    nextLink: onhand/indexquery?pageNumber={pageNumber+1}&pageSize={pageSize}
}

Когда запрос достигает последнего склада (locationId), nextLink значение представляет собой пустую строку.

API версии 2.0 также позволяет указать в запросе несколько кодов организации. Для этого введите в фильтр документа запроса список с разделителем-запятыми список кодов organizationId организаций. Например, . "organizationId": ["org1", "org2", "org3"]

Запрос с использованием метода GET

Path:
    /api/environment/{environmentId}/onhand
Method:
    Get
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Query(Url Parameters):
    groupBy
    returnNegative
    [Filters]

Пример URL-адреса GET. Этот запрос GET в точности совпадает с приведенным ранее примером POST.

/api/environment/{environmentId}/onhand?organizationId=SCM_IV&productId=iv_contoso_product&siteId=iv_contoso_site&locationId=iv_contoso_location&colorId=red&groupBy=colorId,sizeId&returnNegative=true

Система не поддерживает запросы запасов по нескольким кодам организации с использованием метода GET.

Точный запрос запасов в наличии

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

  • Сайт 1, который сопоставлен с расположением A
  • Сайт 2, который сопоставлен с расположением B

Для обычного запроса запасов в наличии, если указано "siteId": ["1","2"] и "locationId": ["A","B"], видимость запасов автоматически запрашивает результат для следующих узлов и ячеек:

  • Сайт 1, местоположение A
  • Сайт 1, местоположение B
  • Сайт 2, местоположение A
  • Сайт 2, местоположение B

Как вы видите, обычный запрос запасов в наличии не распознает, что местоположение A существует только на сайте 1, а местоположение B существует только на сайте 2. Таким образом, он выполняет избыточные запросы. Чтобы учесть эту иерархию сопоставления, можно использовать точный запрос запасов в наличии и указать сопоставления местоположений в теле запроса. В этом случае вы запрашиваете и получаете результаты только для сайта 1, местоположения A, и сайта 2, местоположение B.

Точный запрос по запасам с использованием метода разноски

Точный запрос по post API доступен в двух версиях. В следующей таблице описаны различия.

API версии 1.0 API версии 2.0
Может запросить только один код организации. Может запрашивать несколько кодов организации.

Точный запрос по записи API версии 1.0

Path:
    /api/environment/{environmentId}/onhand/exactquery
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        dimensionDataSource: string, # Optional
        filters: {
            organizationId: string[],
            productId: string[],
            dimensions: string[],
            values: string[][],
        },
        groupByValues: string[],
        returnNegative: boolean,
    }

В основной части этого запроса dimensionDataSource является необязательным параметром. Если он не задан, dimensions в filters будет рассматриваться как базовые аналитики. Имеется четыре обязательных поля для filters: organizationId, productId, dimensions и values.

  • organizationId должен содержать только одно значение, но все еще является массивом.
  • productId может содержать одно или несколько значений. Если оно является пустым массивом, будут возвращаться все продукты.
  • В массиве dimensions коды siteId и locationId необходимы только в случае, если для правила разделения данных задано значение По местоположению. В этом случае они могут отображаться с другими элементами в любом порядке.
  • values может содержать один или несколько различных кортежей значений, соответствующих dimensions.

dimensions в filters будут автоматически добавлены в groupByValues.

Этот параметр returnNegative определяет, содержат ли результаты отрицательные значения.

В следующем примере показано содержимое текста примера.

{
    "dimensionDataSource": "pos",
    "filters": {
        "organizationId": ["SCM_IV"],
        "productId": ["iv_contoso_product"],
        "dimensions": ["siteId", "locationId", "colorId"],
        "values" : [
            ["iv_contoso_site", "iv_contoso_location", "red"],
            ["iv_contoso_site", "iv_contoso_location", "blue"],
        ]
    },
    "groupByValues": ["colorId", "sizeId"],
    "returnNegative": true
}

В следующем примере показано, как запросить все продукты на нескольких сайтах и в нескольких местонахождениях.

{
    "filters": {
        "organizationId": ["SCM_IV"],
        "productId": [],
        "dimensions": ["siteId", "locationId"],
        "values" : [
            ["iv_contoso_site_1", "iv_contoso_location_1"],
            ["iv_contoso_site_2", "iv_contoso_location_2"],
        ]
    },
    "groupByValues": ["colorId", "sizeId"],
    "returnNegative": true
}

Точный запрос по записи API версии 2.0

Path:
    /api/environment/{environmentId}/onhand/exactquery
Method:
    Post
Headers:
    Api-Version="2.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        dimensionDataSource: string, # Optional
        filters: {
            productId: string[],
            keys: string[],
            values: string[][],
        },
        groupByValues: string[],
        returnNegative: boolean,
    }

API версии 2.0 отличается от версии 1.0 следующим образом:

  • В filters разделе теперь есть keys поле, а dimensions не поле. Поле keys работает как dimensions поле в версии 1.0, но может теперь также включать organizationId. Ключи можно указать в любом порядке.
  • Раздел filters больше не поддерживает organizationId это поле. Вместо этого можно включить organizationId в поле (например, keys ) один из аналитик keys: ["organizationId", "siteId", "locationId"]и определить значения кода организации для позиции, совпадающей в values поле (например, при values: ["SCM_IV", "iv_contoso_site_1", "iv_contoso_location_1"] необходимости).

Другие поля идентичны API версии 1.0.

Запрос с поиском продуктов

Следующие доступные API-интерфейсы запросов запасов в наличии улучшены для поддержки поиска продуктов:

Примечание

При публикации запроса видимости запасов, использующего поиск продуктов, используйте параметр запроса productSearch (с объектом ProductAttributeQuery внутри), чтобы найти или отфильтровать по идентификатору продукта. Новые API-интерфейсы больше не поддерживают старый параметр запроса productid в тексте запроса.

Необходимые условия

Прежде чем вы сможете начать использовать API-интерфейсы поиска продуктов, ваша система должна соответствовать следующим требованиям:

Контракт поиска продуктов

Контракт на поиск продуктов определяет правила взаимодействия с API-интерфейсами поиска продуктов. Он обеспечивает стандартизированный способ описания возможностей и поведения возможностей поиска продуктов. Таким образом, пользователям будет проще понимать, взаимодействовать и создавать приложения, использующие API-интерфейсы видимости запасов.

В следующем примере показано содержимое контракта.

{
    "productFilter": {
        "logicalOperator": "And",
        "conditions": [
            {
                "conditionOperator": "Contains",
                "productName": [
                    "Deluxe"
                ],
            },
        ],
        "subFilters": [
            {
                "conditions": [
                    {
                        "conditionOperator": "IsExactly",
                        "productType": [
                            "Item"
                        ]
                    }
                ]
            }
        ]
    },
    "attributeFilter": {
        "logicalOperator": "Or",
        "conditions": [
            {
                "attributeName": "Weight Limit",
                "attributeTypeName":"PoundDomain",
                "attributeArea": " ProductAttribute",
                "attributeValues": [
                    "370"
                ],
                "conditionOperator": "GreaterEqual"
            }
        ],
        "subFilters": [
            {
                "conditions": [
                    {
                        "attributeName": "Weight Limit",
                        "attributeTypeName":"PoundDomain",
                        "attributeArea": " ProductAttribute",
                        "attributeValues": [
                            "330"
                        ],
                        "conditionOperator": "LessEqual"
                    }
                ]
            }
        ]
    },
}

В следующей таблице описываются поля, которые используются в контракте.

Код поля Описание
logicalOperator Возможные значения: And и Or. Используйте это поле для подключения нескольких условий либо условий и вложенных фильтров. Обратите внимание, что subFilters на самом деле представляют собой объект productFilter или attributeFilter. Таким образом, вы можете иметь subFilters внутри subFilters.
conditionOperator Возможные значения: IsExactly, IsNot, Contains, DoesNotContain, BeginsWith, IsOneOf, GreaterEqual, LessEqual и Between.
ProductFilter Используйте это поле для фильтрации продуктов по информации, связанной с продуктом. Например, вы можете изменить productName в контракте на Company, itemNumber, productSearchName, productType, productName, productDescription, inventoryUnitSymbol, salesUnitSymbol или purchaseUnitSymbol в соответствии с потребностями вашего бизнеса.
AttributeFilter Используйте это поле для фильтрации продуктов по информации, связанной с атрибутом.
attributeArea Возможные значения: ProductAttribute, DimensionAttribute и BatchAttribute.
Path:
    /api/environment/{environmentId}/onhand/productsearch/indexquery
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        productSearch: {ProductAttributeQuery contract object inherited from Product Search}
            dimensionDataSource: string, # Optional
            filters: {
                organizationId: string[],
                siteId: string[],
                locationId: string[],
                [dimensionKey:string]: string[],
            },
            groupByValues: string[],
            returnNegative: boolean,
    }

В следующем примере показано содержимое текста примера.

{
    "productSearch": {
        "productFilter": {
            "conditions": [
                {
                    "conditionOperator": "contains",
                    "productName": [
                        "speaker cable"
                    ],
                },
            ],
        },
    },
    "returnNegative": true, 
    "filters": 
    {
        "organizationId": ["usmf"], 
        "siteId": ["1"], 
        "locationId": ["13"],
    },
    "groupByValues": ["colorid"],
}

В следующем примере показан успешный ответ.

[
    {
        "productId": "M0030",
        "dimensions": {
            "ColorId": "White",
            "siteid": "1",
            "locationid": "13"
        },
        "quantities": {
            "fno": {
                "arrived": 0,
                "availordered": 20,
                "onorder": 5,
                "ordered": 20,
                "physicalinvent": 0,
                "reservordered": 0,
                "reservphysical": 0,
                "orderedsum": 20,
                "softreserved": 0
            },
            "iv": {
                "ordered": 0,
                "softreserved": 0,
                "softreservphysical": 0,
                "softreservordered": 0,
                "total ordered": 20,
                "total on order": 5,
                "availabletoreserve": 20,
                "totalavailable": 20,
                "totalordered": 20,
                "totalonorder": 5
            },
            "pos": {
                "inbound": 0,
                "outbound": 0
            },
            "@iv": {
                "@allocated": 0
            }
        }
    },
    {
        "productId": "M0030",
        "dimensions": {
            "ColorId": "Black",
            "siteid": "1",
            "locationid": "13"
        },
        "quantities": {
            "fno": {
                "arrived": 0,
                "availordered": 3,
                "ordered": 3,
                "physicalinvent": 0,
                "reservordered": 0,
                "reservphysical": 0,
                "orderedsum": 3,
                "softreserved": 0
            },
            "iv": {
                "ordered": 0,
                "softreserved": 0,
                "softreservphysical": 0,
                "softreservordered": 0,
                "total ordered": 3,
                "availabletoreserve": 3,
                "totalavailable": 3,
                "totalordered": 3
            },
            "pos": {
                "inbound": 0,
                "outbound": 0
            },
            "@iv": {
                "@allocated": 0
            }
        }
    }
]
Path:
    /api/environment/{environmentId}/onhand/productsearch/exactquery
Method:
    Post
Headers:
    Api-Version="1.0"
    Authorization="Bearer $access_token"
ContentType:
    application/json
Body:
    {
        productSearch: {ProductAttributeQuery contract object inherited from Product Search}
            dimensionDataSource: string, # Optional
            filters: {
                organizationId: string[],
                dimensions: string[],
                values: string[][],
            },
            groupByValues: string[],
            returnNegative: boolean,
    }

В следующем примере показано содержимое текста примера.

{
    "productSearch": {
        "productFilter": {
            "conditions": [
                {
                    "conditionOperator": "contains",
                    "productName": [
                        "speaker cable"
                    ],
                },
            ],
        },
    },
    "filters": {
        "organizationId": ["usmf"],
        "dimensions": ["siteId", "locationId", "colorid"],
        "values" : [
            ["1", "13", "Black"],
        ]
    },
    "groupByValues": [],
    "returnNegative": true
}

В следующем примере показан успешный ответ.

[
    {
        "productId": "M0030",
        "dimensions": {
            "ColorId": "Black",
            "siteid": "1",
            "locationid": "13"
        },
        "quantities": {
            "fno": {
                "arrived": 0,
                "availordered": 3,
                "ordered": 3,
                "physicalinvent": 0,
                "reservordered": 0,
                "reservphysical": 0,
                "orderedsum": 3,
                "softreserved": 0
            },
            "iv": {
                "ordered": 0,
                "softreserved": 0,
                "softreservphysical": 0,
                "softreservordered": 0,
                "total ordered": 3,
                "availabletoreserve": 3,
                "totalavailable": 3,
                "totalordered": 3
            },
            "pos": {
                "inbound": 0,
                "outbound": 0
            },
            "@iv": {
                "@allocated": 0
            }
        }
    }
]

Доступно для резервирования

Можно настроить видимость запасов, чтобы можно было планировать будущие изменения запасов в наличии и рассчитывать количества ATP. ATP — это количество номенклатуры, которое доступно и может быть зарезервировано для клиента в следующем периоде. Использование расчета ATP может значительно повысить возможности выполнения заказов. Сведения о том, как включить эту функцию и как работать с видимостью запасов через его API после включения функции, см. в разделе Графики изменения запасов в наличии и доступность для заказа.

Распределение

Интерфейсы API, связанные с распределением, настраиваются в разделе Распределение видимости запасов.