Еще раз про доступность товаров для разных групп покупателей

В прошлый раз не получилось, еще одна попытка.

Подскажите, коллеги, как мне в $product.amount для конкретной группы &auth.usergroup_ids выбрать не общее количество товаров на всех складах, а только товары с конкретного склада?

Где этот самый $product.amount для карточки товара формируется? Не бейте сильно ногами, всю голову сломал, не могу найти.

Тут какая-то путаница — наличие никак не зависит от группы пользователя, в складах зависимость только от местоположения. Ну а далее для начала смотрите app/addons/warehouses/controllers/frontend/warehouses.php

$location_manager = \Tygh::$app[‘location’];
$destination_id = $location_manager->getDestinationId();
$availability = fn_warehouses_get_availability_summary($params[‘product_id’], $destination_id);

Так же можно напрямую брать данные из таблиц warehouses_products_amount и warehouses_destination_products_amount

Никакой путаницы :slight_smile:

Мне нужно показать для конкретной группы только остатки конкретного склада. Я вижу, что в шаблоне вывод такой:

{$product_amount="product_amount_`$obj_id`"}
{$smarty.capture.$product_amount nofilter}

Потому спрашиваю — как в этот $product_amount попадает общее количество. Как и где?

Или я чего-то не понимаю?

Хук get_products(fn_warehouses_get_products в app/addons/warehouses/func.php)

Посмотрел все массивы в функции. Пока не нашел там общего количества товаров :frowning:

А там таких массивов и нет, но можно посмотреть как меняются запросы для работы с остатками по складам при получении списка товаров. Если же оторваться от этого то остатки мы можем получить через стандартные функции либо через более гибкий вариант написания своих запросов к бд.

Простой путь через стандартные функции в последних версиях cscart
$manager = Tygh::$app['addons.warehouses.manager'];
//Указываем ID товара
$product_stock = $manager->getProductWarehousesStock(180);
//Остатки по местоположению(нужно знать id местоположения пользователя, смотрим fn_warehouses_get_destination_id_by_product_params)
$destination_amount = $product_stock->getAmountForDestination(1);
//Остатки по складу(нужно знать id нужного нам склада)
$warehouse_amount = $product_stock->getAmountForWarehouse(1);

Так же можно посмотреть в сторону функции fetchProductsWarehousesAmounts если у нас есть готовый массив с товарами

Либо

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

Cмотрим как склады работают с остатками(меняют запросы к бд):

Summary
$destination_ids = (empty($params['destination_ids']))
    ? fn_warehouses_get_destination_id_by_product_params($params)
    : $params['destination_ids'];

$join .= db_quote(
    ' LEFT JOIN ?:warehouses_destination_products_amount AS warehouses_destination_products_amount'
    . ' ON warehouses_destination_products_amount.product_id = products.product_id'
    . ' AND warehouses_destination_products_amount.destination_id IN (?n)'
    . ' AND warehouses_destination_products_amount.storefront_id = ?i',
    $destination_ids,
    $storefront_id
);

// FIXME Dirty hack
$condition = str_replace(
    'products.amount',
    db_quote(
        '(CASE products.is_stock_split_by_warehouses WHEN ?s'
        . ' THEN warehouses_destination_products_amount.amount'
        . ' ELSE products.amount END)',
        YesNo::YES
    ),
    $condition
);

Пишем свой запрос для получения остатков в зависимости от того что требуется, например что то такое(Если нам нужны остатки так как их формирует витрина по местоположению):

Запрос остатков по местоположению
$destination_ids = (empty($params['destination_ids']))
    ? fn_warehouses_get_destination_id_by_product_params($params)
    : $params['destination_ids'];

$storefront_id = Tygh::$app['storefront.switcher.selected_storefront_id'];

$product_ids = [1,2,3,4,5];

$warehouses_destination_amounts = db_get_hash_array("SELECT products.product_id as product_id, (CASE products.is_stock_split_by_warehouses WHEN 'Y' 
    THEN war_amount.amount ELSE products.amount END) as amount FROM ?:products AS products 
    LEFT JOIN ?:warehouses_destination_products_amount AS war_amount ON war_amount.product_id = products.product_id 
    AND war_amount.destination_id IN (?n) AND war_amount.storefront_id = ?i
    WHERE products.product_id IN (?n) GROUP BY products.product_id", 'product_id', $destination_ids, $storefront_id, $product_ids);

Если же нам все же нужны остатки с конкретного склада, то берем остатки из таблицы warehouses_products_amount:

Запрос остатков со склада

$warehouse_id = 1;

$product_ids = [1,2,3,4,5];

$warehouses_amounts = db_get_hash_array(“SELECT products.product_id, (CASE products.is_stock_split_by_warehouses WHEN ‘Y’
THEN war_amount.amount ELSE products.amount END) as amount FROM ?:products as products
LEFT JOIN ?:warehouses_products_amount AS war_amount ON war_amount.product_id = products.product_id AND war_amount.warehouse_id = ?i
WHERE products.product_id IN (?n) GROUP BY products.product_id”, ‘product_id’, $warehouse_id, $product_ids);

1 лайк

Ещё немного покурил и поплясал с бубном.

Возможно, я неправильно задал вопрос. Попробую еще раз, ок?

Так должна выглядеть карточка товара на экране обычного покупателя. То есть он видит, что на всех складах (и доступны к заказу) 39 каких-то шапок.

Дилер должен видеть и иметь возможность заказать только товары основного склада. То есть верхний блок «Наличие в магазинах» он вообще не должен видеть. Это просто и не вызывает проблем.

А еще он должен видеть число не 39, а 24 (39 - (8 + 7)).

Именно эта часть вызывает проблемы. Я могу запросто вытащить из базы нужный остаток. Например, так:

function fn_ecl_get_amount_by_central($product_id = 0)
{
$store_location_id = 14;
if($product_id != 0) {
	$amount = db_get_field("SELECT amount FROM ?:warehouses_products_amount WHERE product_id = ?i AND warehouse_id = ?i", $product_id, $store_location_id);
}
return !empty($amount) ? $amount : 0;
}

Но никак не пойму, как и куда его засунуть, чтоб в шаблоне эта конструкция:

            {assign var="product_amount" value="product_amount_`$obj_id`"}
            {$smarty.capture.$product_amount nofilter}  

вывела то, что мне надо :frowning:

Подебажьте функции в fn_warehouses_gather_additional_products_data_post. Похоже, оттуда ноги растут

1 лайк

Вот спасибо так спасибо!

Первую часть задачи победил с вашей помощью. Спрятал от дилера товар со всех складов кроме центрального.

Да, информацию по продуктам собирает тут:

$products = $manager->fetchProductsWarehousesAmountsByDestination($products, $destination_id, $storefront_id);

Но возникла вторая половина проблемы. Как говорят, откуда не ждали.

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

UPD

сам нашел.

function fn_warehouses_check_amount_in_stock_before_check