Добавление штрих-кодов в Рознице

Клиенту понадобился удобный инструмент для назначения штрих-кодов для характеристик товаров. Дело в том, что у разных товаров в ассортименте был одинаковый код, нужно было назначить новые внутренние штрих-кода на каждую позицию из ассортимента, нанести потом их на этикетку, чтобы товар продавался по каждой характеристике отдельно.

Решил, что самое удобное место, чтобы назначать штрих-кода — это обработка печати этикеток и ценников, потому что там можно заполнять остатками товаров, подбирать вручную и заполнять строки обработки из документа.

Добавил кнопку «Назначить ШК» в обработку печати этикеток и ценников:

При ее нажатии открываю дополнительную обработку, куда передаю только выбранные галочками товары:

&НаКлиенте
Процедура дор_дор_НазначитьШтрихкодаПосле(Команда)
   
ПараметрыОбработки = Новый Структура();
   
ПараметрыОбработки.Вставить(«Коллекция», Новый Массив());
    Для Каждого
Строка ИЗ Объект.Товары Цикл
        Если НЕ
Строка.Выбран Тогда
            Продолжить;
        КонецЕсли;
       
ПараметрыОбработки.Коллекция.Добавить(
        Новый
Структура(«Номенклатура, Характеристика», Строка.Номенклатура, Строка.Характеристика)
        );
    КонецЦикла;
   
ОткрытьФорму(«Обработка.дор_НазначитьШК.Форма.Форма», ПараметрыОбработки);
КонецПроцедуры

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

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

Штрих-кода я вычисляю отдельными запросами. Это не очень производительно, но и не очень критично.

Как назначать штрих-код, сразу не нашел. В форме характеристики и номенклатуры кнопки не нашел соответствующей кнопки. Пришлось запустить поиск по префиксу внутреннего ШК:

В итоге была найдена функция СформироватьШтрихкод в модуле ПодключаемоеОборудованиеРТВызовСервера. Внимание! Она работает только для EAN13!

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

Чтобы дважды не получать список штрих-кодов, сериализовал их в строку, получил сообщение «Ошибка формата потока»:

Оказывается, по ошибке для хранения сериализированной строки использовал строку длиной 10 (по умолчанию), расширил до нуля — заработало.

Отладка на сервере не работала. Поэтому очищать наборы записей было рискованно без проверки — можно было бы очистить весь регистр штрих-кодво. Пришлось написать код, который сообщал о количестве удаляемых записей:

НЗ.Прочитать();
//НЗ.Записать();
Сообщить(Символы.Таб + «Старых записей: » + НЗ.Количество());
Сообщить(Символы.Таб + «Удален ШК: » + ШтрихКод);

После этого последовательно запустил и проверил протокол для разных операций:

Убедился, что все отрабатывает корректно, как задумано.

Потом еще была ошибка, что «Тип штрихкода» — это не перечисление «Типы штрихкодов» а одноименное ПВХ. Хотя и перечисление в конфигурации тоже имеется, что затруднило диагностику.

Также после назначения ШК нужно их перезаполнять, иначе может быть такая ситуация:

Т.е. если нажать несколько раз «Назначить ШК», обработка не узнает, что новые ШК уже созданы. Поэтому нужно обновлять колонку «Штрих-коды» после назначения ШК.

Время факт: 2 час. Розница 2.3.4.33

Итоговый код обработки:


&НаСервере
Процедура НазначитьШКНаСервере()


    Для Каждого
Строка ИЗ Объект.Состав Цикл

       
ШтрихКоды = ЗначениеИзСтрокиВнутр(Строка.ШтрихКодыСтрокой);
       
ВнешниеШК = Новый Массив();
       
ВнутренниеШК = Новый Массив();

       
ЕстьВнутренний = ложь;
        Для Каждого
ШтрихКод ИЗ ШтрихКоды Цикл
            Если
Лев(ШтрихКод, СтрДлина(ПрефиксШК)) = ПрефиксШК Тогда
               
ЕстьВнутренний = истина;
               
ВнутренниеШК.Добавить(ШтрихКод);
            Иначе
               
ВнешниеШК.Добавить(ШтрихКод);
            КонецЕсли;
        КонецЦикла;
       
ЕстьШК = ШтрихКоды.Количество() > 0;

       
//Обработки по умолчанию
       
ЗаписатьНовыйШК = ложь;
       
ОчищатьВнешниеШК = ложь;

       
//Определяем вид обработки и что нужно делать
       
Если ВидОбработки = «ТолькоВнутренний» Тогда
            Если НЕ
ЕстьВнутренний Тогда
               
ЗаписатьНовыйШК = истина;
            КонецЕсли;
           
ОчищатьВнешниеШК = истина;
        ИначеЕсли
ВидОбработки = «ДобавлятьВнутренний» Тогда
            Если НЕ
ЕстьВнутренний Тогда
               
ЗаписатьНовыйШК = истина;
            КонецЕсли;
        ИначеЕсли
ВидОбработки = «» Тогда
            Если НЕ
ЕстьШК Тогда
               
ЗаписатьНовыйШК = истина;
            КонецЕсли;
        КонецЕсли;

       
Сообщить(«Номенклатура: » + Строка.Номенклатура + » хар-ка: » + Строка.Характеристика);
        Если
ОчищатьВнешниеШК Тогда
            Для Каждого
ШтрихКод ИЗ ВнешниеШК Цикл
               
НЗ = РегистрыСведений.ШтрихКоды.СоздатьНаборЗаписей();

               
НЗ.Отбор.Штрихкод.Значение = ШтрихКод;
               
НЗ.Отбор.Штрихкод.Использование = истина;

               
НЗ.Отбор.Владелец.Значение = Строка.Номенклатура;
               
НЗ.Отбор.Владелец.Использование = истина;

               
НЗ.Отбор.Характеристика.Значение = Строка.Характеристика;
               
НЗ.Отбор.Характеристика.Использование = истина;

               
//НЗ.Прочитать();
               
НЗ.Записать();
               
//Сообщить(Символы.Таб + «Старых записей: » + НЗ.Количество());
               
Сообщить(Символы.Таб + «Удален ШК: » + ШтрихКод);
            КонецЦикла;
        КонецЕсли;

        Если
ЗаписатьНовыйШК Тогда
           
ШтрихКод = ПодключаемоеОборудованиеРТВызовСервера.СформироватьШтрихкод(ПрефиксШК);
           
МЗ = РегистрыСведений.ШтрихКоды.СоздатьМенеджерЗаписи();
           
МЗ.Штрихкод = ШтрихКод;
           
МЗ.Владелец = Строка.Номенклатура;
           
МЗ.Характеристика = Строка.Характеристика;
           
МЗ.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
           
МЗ.Записать();
           
Сообщить(Символы.Таб + «Добавлен ШК: » + ШтрихКод);
        КонецЕсли;
    КонецЦикла;

   
ОбновитьШтрихКоды();
КонецПроцедуры

&НаКлиенте
Процедура НазначитьШК(Команда)
   
НазначитьШКНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

   
УстановитьПривилегированныйРежим(истина);
   
ПрефиксШК = Константы.ПрефиксВнутреннегоШтрихкодаШтучногоТовара.Получить();
   
Объект.Состав.Очистить();

    Для Каждого
Строка ИЗ Параметры.Коллекция Цикл

       
НСтр = Объект.Состав.Добавить();
       
НСтр.Номенклатура = Строка.Номенклатура;
       
НСтр.Характеристика = Строка.Характеристика;
    КонецЦикла;

   
ОбновитьШтрихКоды();
КонецПроцедуры

&НаСервере
Процедура ОбновитьШтрихКоды()
    Для Каждого
Строка ИЗ Объект.Состав Цикл
       
СтруктураШК = ПолучитьШтрихКоды(Строка.Номенклатура, Строка.Характеристика);
       
Строка.ШтрихКоды = СтруктураШК.ШтрихКоды;
       
Строка.ШтрихКодыСтрокой = СтруктураШК.ШтрихКодыСтрокой;
    КонецЦикла;
КонецПроцедуры


&НаСервере
Функция ПолучитьШтрихКоды(Номенклатура, Характеристика)
   
Р = Новый Структура(«ШтрихКоды,ШтрихКодыСтрокой»);

   
Запрос = Новый Запрос(
   
«ВЫБРАТЬ
    |   Т.Штрихкод КАК Штрихкод,
    |   Т.Владелец КАК Номенклатура,
    |   Т.Характеристика КАК Характеристика
    |ИЗ
    |   РегистрСведений.Штрихкоды КАК Т
    |ГДЕ
    |   Т.Владелец = &Номенклатура
    |   И Т.Характеристика = &Характеристика
    |   И Т.Владелец ССЫЛКА Справочник.Номенклатура»
);

   
Запрос.УстановитьПараметр(«Номенклатура», Номенклатура);
   
Запрос.УстановитьПараметр(«Характеристика», Характеристика);
   
ТЗ = Запрос.Выполнить().Выгрузить();

   
Р.ШтрихКоды = «»;
    Для Каждого
Строка ИЗ ТЗ Цикл
       
Р.ШтрихКоды = Р.ШтрихКоды + ?(Р.ШтрихКоды = «», «», «,») + Строка.ШтрихКод;
    КонецЦикла;

   
Р.ШтрихКодыСтрокой = ЗначениеВСтрокуВнутр(ТЗ.ВыгрузитьКолонку(«ШтрихКод»));
   
//Сообщить(Р.ШтрихКодыСтрокой);

   
Возврат Р;

КонецФункции

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

комментария 4

  1. fajij28770:

    о, вложенный в цикл запрос — классика плохого кодирования. кстати, это не ты ли писал когда-то, что твой код в облако не приняли из-за таких запросов?

    • Не стоит фанатично подходить к таким запретам. Если скорость разработки важнее производительности, можно использовать запросы в цикле. Без проблем.

  2. fajij28770:

    ты так пишешь, как будто вынести запрос из цикла — это какой-то rocket science

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *