Availability
- Document schema
- Collection setup
- Exporting availabilities
- Requesting a scope
- Reading hits
- Suggestions
Status, price and stock of a product can differ per country or sales channel. Like the translations, all scopes are exported in one document and the gateway delivers only the requested one. The module works next to the translations and does not change them.
Document schema
The default values stay in _PRODUCT, the scoped values are stored in _PRODUCT_availability.<scope>:
{
"id": "PRODUCT-1002",
"type": "PRODUCT",
"_PRODUCT_availability": {
"de": {"active": true, "price": 1337.0},
"ch": {"active": false, "instock": 0}
},
"_PRODUCT": {
"id": "1002",
"name": "Ultra HD LED-TV 65\"",
"price": 999.0,
"active": true,
"instock": 14
}
}
Collection setup
Configure a second variable in the BatteryIncluded backend:
{"name": "availability", "default": "de", "root": ["_PRODUCT_availability"]}
Exporting availabilities
use BatteryIncludedSdk\Dto\ProductBaseDto;
$product = new ProductBaseDto('1002');
$product->setId('1002');
$product->setPrice(999.0); // default values
$product->setActive(true);
$product->setInstock(14);
$product
->setAvailability('de', active: true, price: 1337.0)
->setAvailability('ch', active: false, instock: 0)
->addAvailability('at', 'price', 1029.0);
| Method | Description |
|---|---|
setAvailability($scope, active:, price:, instock:) | Set several fields of a scope, null keeps the default |
addAvailability($scope, $field, $value) | Set a single field of a scope |
getAvailability($scope) / getAvailabilities() | Read the availabilities back |
ProductBaseDtoaccepts the fieldsactive,priceandinstock, other fields throw anInvalidArgumentException. Custom DTOs extendAbstractAvailabilityDtoand overridegetAvailabilityFields().- Scopes are normalized like locales:
DEbecomesde,b2b_DEbecomesb2b-de. falseand0overwrite the default (inactive, out of stock),nulland empty values do not.
Requesting a scope
$searchStruct = new BrowseSearchStruct();
$searchStruct->setLocale('de');
$searchStruct->setAvailability('ch'); // or $searchStruct->addVariable('availability', 'ch')
- Without
setAvailability()the SDK sends nov[availability], thedefaultof the variable applies. - There is no fallback between scopes: if a document lacks the requested scope, the default values apply.
Reading hits
BrowseResponse::getHits() merges the translations first and then the availability into _PRODUCT, so the availability wins for fields which are in both nodes:
$result = (new BrowseService($apiClient))->browse($searchStruct);
foreach ($result->getHits() as $hit) {
$product = $hit['document']['_PRODUCT'];
echo $product['active'] ? $product['price'] : 'not available';
}
$result->getRawHits(); // untouched response including _PRODUCT_availability
$result->getAvailability(); // requested scope, null for the default
Use AvailabilityResolver::resolveDocument($document, $scope) to resolve documents from other sources the same way.
Suggestions
SuggestSearchStruct::setAvailability() works the same way. The suggest endpoint delivers only the fields selected under Suggest in the portal, select price (and active or instock for a status) to show them in the dropdown. The documents are returned as delivered, resolve them with the resolver:
$suggest = new SuggestSearchStruct();
$suggest->setQuery('smart');
$suggest->setLocale('de');
$suggest->setAvailability('ch');
foreach ((new SuggestService($apiClient))->suggestWithFilter($suggest)->getDocuments() as $document) {
$product = AvailabilityResolver::resolveDocument($document, 'ch')['_PRODUCT'];
echo $product['price'] ?? '';
}
Filters and sortings on _PRODUCT.price or _PRODUCT.active use the default values. Filter scoped values with their node, e.g. _PRODUCT_availability.active, once the field is configured as filterable in the portal.