I already experienced this same problem with Craft Commerce a while ago (Error on functions in queue: "Session does not exist in a console request.") and got a solution that solved the problem for the function described in that question, but this time the problem occurs on a different function and I can't seem to find a solution.
There's a connection with the Lightspeed API to update product stock values every 15 minutes and to import new products. These are all handled by the queue and work most of the time, but sometimes it throws an error saying "Session does not exist in a console request"
Here are all functions that are performed in this action (I know it's a lot, but I am getting quite desperate):
Controller action
public function actionImportNewProducts()
{
Stock::$plugin->lightspeedService->refreshToken();
$allowedCategories = Craft::$app->request->getBodyParam('categories');
$startParam = Craft::$app->request->getBodyParam('startDate');
$startDate = new \DateTime($startParam['date']);
$endParam = Craft::$app->request->getBodyParam('endDate');
if (!$endParam) {
$endDate = new \DateTime();
} else {
$endDate = new \DateTime($endParam['date']);
}
$endDate = $endDate->modify('tomorrow midnight');
$limit = 100;
$pages = Stock::$plugin->lightspeedService->getPagination();
$productCount = 0;
for ($page = 0; $page < $pages; $page++) {
$offset = $page * $limit;
$inventory = json_decode(Stock::$plugin->lightspeedService->getInventory($offset, '["ItemShops", "Category", "TaxClass"]'), true);
$items = $inventory['Item'];
foreach ($items as $item) {
$createdAt = new \DateTime($item['createTime']);
$createdAt = $createdAt->modify('midnight');
if ($createdAt >= $startDate && $createdAt <= $endDate) {
$category = $item['Category'];
if (in_array($category['categoryID'], $allowedCategories)) {
if (!$item['archived'] or $item['archived'] == 'false') {
Stock::$plugin->productService->queueImportProduct($item);
$productCount++;
}
}
}
}
}
Craft::$app->session->setNotice($productCount . ' producten aan het importeren.');
}
LightspeedService refreshToken
public function refreshToken()
{
$refreshToken = Stock::getInstance()->settings->refreshToken;
if (!$refreshToken) {
Craft::$app->session->setError('Lightspeed refreshtoken ontbreekt');
return false;
}
$client = new GuzzleClient();
$url = 'https://cloud.lightspeedapp.com/oauth/access_token.php';
$body['multipart'] = [
[
'name' => 'client_id',
'contents' => getenv('LIGHTSPEED_CLIENT_ID')
],
[
'name' => 'client_secret',
'contents' => getenv('LIGHTSPEED_CLIENT_SECRET')
],
[
'name' => 'refresh_token',
'contents' => $refreshToken
],
[
'name' => 'grant_type',
'contents' => 'refresh_token'
]
];
try {
$request = $client->request('POST', $url, $body);
$response = $request->getBody()->getContents();
$response = json_decode($response);
$accessToken = $response->access_token;
if (!$accessToken) {
return $this->asJson($response);
}
$settings['accessToken'] = $accessToken;
$plugin = Craft::$app->getPlugins()->getPlugin('stock');
Craft::$app->getPlugins()->savePluginSettings($plugin, $settings);
return $response;
} catch (ClientException $e) {
return $e->getMessage();
}
}
LightspeedService getPagination
public function getPagination()
{
$inventory = json_decode(Stock::$plugin->lightspeedService->getInventory(), true);
$attributes = $inventory['@attributes'];
$count = intval($attributes['count']);
$limit = intval($attributes['limit']);
return ceil($count / $limit);
}
LightspeedService getInventory
public function getInventory($offset = 0, $relations = null)
{
Stock::$plugin->lightspeedService->refreshToken();
$client = new GuzzleClient();
$url = getenv('LIGHTSPEED_API_URL') . '/API/Account/' . getenv('LIGHTSPEED_ACCOUNT_ID') . '/Item.json?offset=' . $offset;
if ($relations) {
$url = $url . "&load_relations={$relations}";
}
$headers = [
'Authorization' => 'Bearer ' . Stock::getInstance()->settings->accessToken
];
try {
$request = $client->request('GET', $url, [
'headers' => $headers
]);
$response = $request->getBody()->getContents();
return $response;
} catch (ClientException $e) {
return $e->getMessage();
}
}
ProductService queueImportProduct
public function queueImportProduct($item)
{
Craft::$app->queue->push(new ImportProduct([
'item' => $item
]));
}
Job importProduct
public function execute($queue)
{
Stock::$plugin->productService->importProduct($this->item);
}
ProductService importProduct
I had read in another question that it could help to replace all product updates by DB queries, but that didn't solve my problem.
public function importProduct($item)
{
$sku = $item['systemSku'];
$price = Stock::$plugin->lightspeedService->getDefaultPrice($item);
$stock = Stock::$plugin->lightspeedService->getItemQoh($item);
$productTypeId = Stock::$plugin->productService->getProductType($item['Category']);
$taxCategoryId = Stock::$plugin->lightspeedService->getTaxCategoryId($item['TaxClass']['taxClassID']);
$variant = Variant::find()->sku($sku)->one();
if (!$variant) {
$product = new Product();
$product->typeId = $productTypeId;
$product->enabled = false;
$product->title = $item['description'];
$product->promotable = true;
$product->taxCategoryId = $taxCategoryId;
$variant = new Variant();
$variant->isDefault = true;
$variant->sku = $sku;
$variant->price = (float) $price;
$variant->stock = $stock;
$product->setVariants([$variant]);
Craft::$app->elements->saveElement($product);
} else {
$product = $variant->product;
Craft::$app->getDb()->createCommand()->update('{{%commerce_products}}',
[
'taxCategoryId' => $taxCategoryId,
],
[
'id' => $variant->product->id
]
)->execute();
Craft::$app->getDb()->createCommand()->update('{{%commerce_variants}}',
[
'sku' => $sku,
'price' => (float) $price,
'stock' => $stock
],
[
'id' => $variant->id
]
)->execute();
}
$lightspeedProductRecord = LightspeedProductsRecord::findOne(['itemId' => $item['itemID']]);
if (!$lightspeedProductRecord) {
$lightspeedProductRecord = new LightspeedProductsRecord();
$lightspeedProductRecord->itemId = $item['itemID'];
}
$lightspeedProductRecord->variantId = $variant->id;
$lightspeedProductRecord->save();
}
Any help will be appreciated!