РАЗРАБОТКА НА БИТРИКС

Быстрая групповая привязка товаров к разделам и отвязка от них по номеру артикула

Подписывайтесь на канал для bitrix-разработчиков в Telegram!
В данном кейсе рассмотрен функционал быстрой привязки товаров к нескольким разделам группами, через артикулы.

Описание задачи

Необходимо сделать функционал быстрой привязки товаров к разделу, указав список артикулов и привязки к разделам.

Решение

Создать раздел в административной части с интерфейсом групповой привязки товаров к разделам или отвязки от них, указав перечисление артикулов. При отправке формы перебирать артикулы и записывать все привязки товара к разделам.
Добавляем элемент интерфейса в админ-панель
В init.php или в файле обработчиков объявляем функцию

AddEventHandler('main', 'OnBuildGlobalMenu', ["Oneway\Eventhandlers", "ShowBindIcon"]);
В классе добавляем функцию

namespace Oneway;

class Eventhandlers
{
    function ShowBindIcon(&$aGlobalMenu, &$aModuleMenu)
    {
        $aModuleMenu[] = [
            'parent_menu' => 'global_menu_store', // раздел в котором выводим 
            'sort'        => 97, // сортировка
            'text'        => 'Привязка товаров к разделу', //Название пункта
            'title'       => 'Привязка товаров к разделу',
            'icon'        => 'sale_menu_icon_buyers_affiliate', // Иконка, берем подходящуу системную
            'url'         => 'site_bind_goods.php', // ссылка на файл /bitrix/admin/
        ];
    }
}
Делаем ссылку из админ-панели
Создаем файл, указанный в обработчике /bitrix/admin/site_bind_goods.php
Делаем в нем только ссылку на наш файл

<? require_once($_SERVER['DOCUMENT_ROOT'] . '/local/admin/site_bind_goods.php');

Создаем интерфейс и функционал привязки
Создаем файл /local/admin/site_bind_goods.php с логикой работы
  • Константы

$IBLOCK_ID = \Oneway\Constants::IBLOCK_CATALOG; // инфоблок товаров
\Oneway\Constants::IBLOCK_BACKUP_SECTION_LINK; // Инфоблок бекапов, доп интеграции
  • Обработчик сохранения
Код свойства артикул - CML2_ARTICLE, заменить при необходимости

<?
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php');
use Bitrix\Iblock\PropertyIndex\Manager;
use Bitrix\Sale\GoodsSectionTable;
use Oneway\Iblock\Helper;

global $APPLICATION;
$saleModulePermissions = $APPLICATION->GetGroupRight('sale');
if ($saleModulePermissions < 'R') {
    $APPLICATION->AuthForm(GetMessage('ACCESS_DENIED'));
}

$APPLICATION->SetTitle('Привязка товаров');


$IBLOCK_ID = \Oneway\Constants::IBLOCK_CATALOG;
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
$arResult = [];
//Когда отправлена форма
if(!empty($request->get('goods')) && !empty($request->get('IBLOCK_SECTION1'))){
    $section_list = $request->get('IBLOCK_SECTION1');
    $bind = $request->get('BIND');

		// собираем артикулы, каждый с новой строки
    $goods_list = explode("\r\n",$request->get('goods'));

    $arArticles = [];
    foreach ($goods_list as $row) {
        if(empty($row)) continue;
        preg_match('/([^\\s]+)/', $row, $matches);
        $arArticles[$matches[0]] = $matches[0];
    }

		// делаем выборку товаров по артикулам
    $arSort = array('SORT' => 'ASC');
    $arFilter = array('IBLOCK_ID' => $IBLOCK_ID, "PROPERTY_CML2_ARTICLE" => $arArticles);
    $arSelect = array('ID', 'NAME', 'DETAIL_PAGE_URL','PROPERTY_CML2_ARTICLE');

    $res = CIBlockElement::getList($arSort, $arFilter, false, array(), $arSelect);
		// собирае ID товаров, делаем массив товар=артикул
    while ($row = $res->fetch()) {
        $goodsIds[]=$row['ID'];
        $articlesToID[$row['ID']]=$row['PROPERTY_CML2_ARTICLE_VALUE'];
    }
		
		//выбираем все разделы для собранных товаров
    $res = CIBlockElement::GetElementGroups(
        $goodsIds,
        true,
        ['ID', 'IBLOCK_ELEMENT_ID']
    );

		// Собираем массив ID-товара=Список разделов
    while ($arSecTree = $res->Fetch()) {
        $arProductsSections[$arSecTree['IBLOCK_ELEMENT_ID']][] = $arSecTree['ID'];
    }
		//далее записываем выбранным товарам привязки, либо отвязывае товары
    $k = 0;
    $arResult['count'] = 0;
    foreach($arProductsSections as $id => $sectionsIds){
        $new=[];
        if($bind=='bind_on') { // если привязываем
            $new = array_unique(array_merge($section_list, $sectionsIds));
        } else { //если нудно отвязать
            $new = array_diff($sectionsIds, $section_list);
        }
				// Обновляем привязки товаров к разделам
        if(CIBlockElement::SetElementSection($id, $new)) $k++;
        // Обновим фасетный индекс
        Manager::updateElementIndex(Helper::getIblockIdByCode('catalog'), $id);
    }
		// собираем количество обновленных артикулов, для вывода в интерфейсе
    $arResult['count'] = $k;
}

//Далее идет интерфейс админки
  • Форма интерфейса
После данной обработки (пункт выше) подключается админ-пролог и выводится форма интерфейса.
Быстрая привязка товаров к разделам в 1С-Битрикс - KISLOROD

<?
IncludeModuleLangFile(__FILE__);

require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php');

// вкладки
$aTabs = [
    [
        'DIV' => 'bind_goods',
        'TAB' => 'Привязка товаров',
        'TITLE' => 'Привязка товаров'
    ]
];

?>
<style>
    #bind_goods{
        margin-bottom: 12px;
    }
</style>

    <form name="exchange_form" id="bind_form" action="<? $APPLICATION->GetCurPage() ?>"
          enctype="multipart/form-data" method="post">
        <?
        $tabControl = new CAdminTabControl('tabControl', $aTabs);
        $tabControl->Begin();
        $tabControl->BeginNextTab();

        if (empty($arResult)):
        ?>
            <table class="adm-detail-content-table edit-table">
                <tbody>
                <tr>
                    <td class="adm-detail-content-cell-l" width="40%">
                        Разделы
                    </td>
                    <td class="adm-detail-content-cell-r">
                        <table>
                            <tr id="tr_SECTIONS">
                                <td width="60%">
                                    <table id="sections" class="internal">
                                    </table>
                                    <script type="text/javascript">
                                        function deleteRow(button)
                                        {
                                            var my_row = button.parentNode.parentNode;
                                            var table = document.getElementById('sections');
                                            if(table)
                                            {
                                                for(var i=0; i<table.rows.length; i++)
                                                {
                                                    if(table.rows[i] == my_row)
                                                    {
                                                        table.deleteRow(i);
                                                    }
                                                }
                                            }
                                        }
                                        function InS<?echo md5("input_IBLOCK_SECTION")?>(section_id, html)
                                        {
                                            var table = document.getElementById('sections');
                                            if(table)
                                            {
                                                if(section_id > 0 && html)
                                                {
                                                    var cnt = table.rows.length;
                                                    var oRow = table.insertRow(cnt-1);

                                                    var i=0;
                                                    var oCell = oRow.insertCell(i++);
                                                    oCell.innerHTML = html;

                                                    var oCell = oRow.insertCell(i++);
                                                    oCell.innerHTML =
                                                        '<input type="button" value="Удалить" OnClick="deleteRow(this)">'+
                                                        '<input type="hidden" name="IBLOCK_SECTION1[]" value="'+section_id+'">';
                                                }
                                            }
                                        }
                                    </script>
                                    <input type="button" value="Добавить..." onClick="jsUtils.OpenWindow('/bitrix/admin/iblock_section_search.php?lang=<?echo LANGUAGE_ID?>&amp;IBLOCK_ID=<?echo $IBLOCK_ID?>&amp;n=input_IBLOCK_SECTION&amp;m=y&amp;iblockfix=y&amp;tableId=iblocksection-<?=$IBLOCK_ID; ?>', 900, 700);">
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
                <tr>
                    <td class="adm-detail-content-cell-l" width="40%">
                        Привязать товары к разделам
                    </td>
                    <td class="adm-detail-content-cell-r">
                        <input type="radio" name="BIND" checked="checked" value="bind_on" id="designed_checkbox_0.7335957355994811" class="adm-designed-checkbox">
                        <label class="adm-designed-checkbox-label" for="designed_checkbox_0.7335957355994811" title=""></label>
                    </td>
                </tr>
                <tr>
                    <td class="adm-detail-content-cell-l" width="40%">
                        Отвязать товары от разделов
                    </td>
                    <td class="adm-detail-content-cell-r">
                        <input type="radio" name="BIND" value="bind_off" id="designed_checkbox_del_disk" class="adm-designed-checkbox">
                        <label class="adm-designed-checkbox-label" for="designed_checkbox_del_disk" title=""></label>
                    </td>
                </tr>
                <tr>
                    <td class="adm-detail-content-cell-l" width="40%">
                        Артикулы
                    </td>
                    <td class="adm-detail-content-cell-r">
                        <textarea name="goods" cols="50" rows="15"></textarea>
                    </td>
                </tr>
                <tr>
                    <td class="adm-detail-content-cell-l" width="40%">
                    </td>
                    <td class="adm-detail-content-cell-r">
                        <input type="submit" value="Загрузить" class="adm-btn-save">
                    </td>
                </tr>
                </tbody>
            </table>
            <div class="adm-info-message">
                Каждый артикул с новой строки
            </div>
        <? else: ?>
            <table class="adm-detail-content-table edit-table">
                <tbody>
                <tr>
            <? if (!empty($arResult['ERRORS'])) : ?>
                <h2>Отчет об ошибках</h2>
                <ul>
                    <? foreach($arResult['ERRORS'] as $error): ?>
                        <li>
                            <span><?=$error?></span>
                        </li>
                    <? endforeach; ?>
                </ul>
            <? else: ?>
                <h2 style="color: #02801f">Обновлено товаров: <?=$arResult['count']?></h2>
            <? endif; ?>
                </tr>
                </tbody>
            </table>
        <? endif; ?>
        <? $tabControl->EndTab(); ?>

        <? $tabControl->End(); ?>
        <?= bitrix_sessid_post(); ?>
    </form>


    <div class="adm-info-message-wrap">
        <div id="log_imp" class="adm-info-message" style="display: none;"></div>
    </div>
<? require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php'); ?>

Результат

Работая через артикулы товаров, можно удобно и быстро привязать либо отвязать товары от разделов, что существенно уменьшает время обработки товара с перемещением по разделам.
Подписывайтесь на канал для bitrix-разработчиков в Telegram!

Рекомендованные статьи