При автоматизации рабочего места кассира (РМК) в конфигурации «1С:Розница» часто возникает задача запретить продажу, если в чеке не указан продавец-консультант. Если реквизит шапки документа проверяется простым обращением к объекту, то для проверки табличной части начинающие разработчики часто сталкиваются со сложностями обращения к коллекции строк.
Разберем типичные ошибки при обращении к строкам таблицы, выясним, как правильно обойти табличную часть циклом, и рассмотрим оптимальные варианты проверки данных перед выполнением оплаты.
Рассмотрим, почему не работают прямолинейные способы обращения к реквизитам таблицы:
Объект.Товары.Продавец вызывает синтаксическую ошибку, так как Объект.Товары — это коллекция строк (таблица), а не конкретная строка. У самой таблицы реквизита Продавец нет.Элементы.Товары.ТекущиеДанные.Продавец возвращает данные только той строки, на которой в данный момент установлен курсор пользователя. Если кассир выбрал строку с заполненным продавцом, но в остальных строках продавцы не указаны, такая проверка ошибочно сочтет весь документ корректным.Разберем по шагам наиболее информативный для кассира алгоритм: перед оплатой мы обходим все строки табличной части Товары, собираем номера строк, где не заполнен продавец, и выводим пользователю понятное предупреждение.
Посмотрим на пример реализации алгоритма:
СтрокиБезПродавца = "";
Для Каждого СтрокаТаб Из Объект.Товары Цикл
Если Не ЗначениеЗаполнено(СтрокаТаб.Продавец) Тогда
СтрокиБезПродавца = СтрокиБезПродавца + Строка(СтрокаТаб.НомерСтроки) + ", ";
КонецЕсли;
КонецЦикла;
Если Не ПустаяСтрока(СтрокиБезПродавца) Тогда
// Удаляем завершающую запятую и пробел в конце сформированной строки
СтрокиБезПродавца = Лев(СтрокиБезПродавца, СтрДлина(СтрокиБезПродавца) - 2);
ЗаголовокИнформации = НСтр("ru = 'Выберите продавца!'");
ТекстИнформации = НСтр("ru = 'Перед пробитием чека необходимо указать продавца в строках: '") + СтрокиБезПродавца;
ОбщегоНазначенияРТКлиент.ВывестиИнформациюДляРМКУправляемой(ЗаголовокИнформации, ТекстИнформации);
Иначе
ОплатитьТовары("ФормаПростойОплаты");
КонецЕсли;
Разберем подробнее работу строковых функций в данном примере:
Строка(СтрокаТаб.НомерСтроки) + ", " преобразует числовой номер строки в текст и добавляет разделитель (запятую с пробелом). В результате получается строка вида "1, 3, 5, ".СтрДлина(СтрокиБезПродавца) вычисляет общую длину строки, а функция Лев(..., Длина - 2) отсекает ровно два последних символа (запятую и пробел), приводя строку к аккуратному виду: "1, 3, 5".Если нет необходимости перечислять кассиру конкретные номера строк, а достаточно просто прервать операцию при обнаружении первой же незаполненной позиции, цикл можно остановить оператором Прервать:
ВсеСтрокиЗаполнены = Истина;
Для Каждого СтрокаТаб Из Объект.Товары Цикл
Если Не ЗначениеЗаполнено(СтрокаТаб.Продавец) Тогда
ВсеСтрокиЗаполнены = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Если ВсеСтрокиЗаполнены Тогда
ОплатитьТовары("ФормаПростойОплаты");
Иначе
ЗаголовокИнформации = НСтр("ru = 'Выберите продавца!'");
ТекстИнформации = НСтр("ru = 'Перед пробитием чека необходимо указать продавца во всех строках!'");
ОбщегоНазначенияРТКлиент.ВывестиИнформациюДляРМКУправляемой(ЗаголовокИнформации, ТекстИнформации);
КонецЕсли;
Проанализируем альтернативный программный метод поиска незаполненных значений без явного написания цикла. В коллекциях данных формы доступен метод НайтиСтроки(), принимающий структуру отбора:
Отбор = Новый Структура("Продавец", ПредопределенноеЗначение("Справочник.ФизическиеЛица.ПустаяСсылка"));
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Если НайденныеСтроки.Количество() > 0 Тогда
ЗаголовокИнформации = НСтр("ru = 'Выберите продавца!'");
ТекстИнформации = НСтр("ru = 'В чеке присутствуют товары без указания продавца!'");
ОбщегоНазначенияРТКлиент.ВывестиИнформациюДляРМКУправляемой(ЗаголовокИнформации, ТекстИнформации);
Иначе
ОплатитьТовары("ФормаПростойОплаты");
КонецЕсли;
Обратим внимание на архитектурные нюансы конфигурации «1С:Розница»:
ОплатитьТовары() формы РМК.ОплатитьТовары() с директивой &Перед или &Вместо.