Как проверить заполненность поля в табличной части перед проведением или оплатой в 1С

Программист 1С v8.3 (Управляемые формы) 1С:Розница Управленческий учет Торговля и дистрибуция
← На главную

При автоматизации рабочего места кассира (РМК) в конфигурации «1С:Розница» часто возникает задача запретить продажу, если в чеке не указан продавец-консультант. Если реквизит шапки документа проверяется простым обращением к объекту, то для проверки табличной части начинающие разработчики часто сталкиваются со сложностями обращения к коллекции строк.

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

Анализ типичных ошибок при обращении к табличной части

Рассмотрим, почему не работают прямолинейные способы обращения к реквизитам таблицы:

  1. Прямое обращение через точку к реквизиту таблицы: конструкция вида Объект.Товары.Продавец вызывает синтаксическую ошибку, так как Объект.Товары — это коллекция строк (таблица), а не конкретная строка. У самой таблицы реквизита Продавец нет.
  2. Использование ТекущиеДанные элемента формы: конструкция Элементы.Товары.ТекущиеДанные.Продавец возвращает данные только той строки, на которой в данный момент установлен курсор пользователя. Если кассир выбрал строку с заполненным продавцом, но в остальных строках продавцы не указаны, такая проверка ошибочно сочтет весь документ корректным.
  3. Преждевременный вызов оплаты внутри цикла: если разместить вызов функции оплаты внутри цикла по строкам, программа будет пытаться инициировать оплату на каждой проверенной валидной строке, не дожидаясь проверки остальных позиций.

Решение 1: Проверка строк в цикле с формированием списка ошибок

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

Посмотрим на пример реализации алгоритма:


СтрокиБезПродавца = "";

Для Каждого СтрокаТаб Из Объект.Товары Цикл
    Если Не ЗначениеЗаполнено(СтрокаТаб.Продавец) Тогда
        СтрокиБезПродавца = СтрокиБезПродавца + Строка(СтрокаТаб.НомерСтроки) + ", ";
    КонецЕсли;
КонецЦикла;

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

Разберем подробнее работу строковых функций в данном примере:

  1. Накопление номеров строк: выражение Строка(СтрокаТаб.НомерСтроки) + ", " преобразует числовой номер строки в текст и добавляет разделитель (запятую с пробелом). В результате получается строка вида "1, 3, 5, ".
  2. Очистка хвоста строки: функция СтрДлина(СтрокиБезПродавца) вычисляет общую длину строки, а функция Лев(..., Длина - 2) отсекает ровно два последних символа (запятую и пробел), приводя строку к аккуратному виду: "1, 3, 5".

Решение 2: Быстрая проверка без сбора номеров строк

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


ВсеСтрокиЗаполнены = Истина;

Для Каждого СтрокаТаб Из Объект.Товары Цикл
    Если Не ЗначениеЗаполнено(СтрокаТаб.Продавец) Тогда
        ВсеСтрокиЗаполнены = Ложь;
        Прервать;
    КонецЕсли;
КонецЦикла;

Если ВсеСтрокиЗаполнены Тогда
    ОплатитьТовары("ФормаПростойОплаты");
Иначе
    ЗаголовокИнформации = НСтр("ru = 'Выберите продавца!'");
    ТекстИнформации = НСтр("ru = 'Перед пробитием чека необходимо указать продавца во всех строках!'");
    ОбщегоНазначенияРТКлиент.ВывестиИнформациюДляРМКУправляемой(ЗаголовокИнформации, ТекстИнформации);
КонецЕсли;

Решение 3: Поиск незаполненных строк через НайтиСтроки

Проанализируем альтернативный программный метод поиска незаполненных значений без явного написания цикла. В коллекциях данных формы доступен метод НайтиСтроки(), принимающий структуру отбора:


Отбор = Новый Структура("Продавец", ПредопределенноеЗначение("Справочник.ФизическиеЛица.ПустаяСсылка"));
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);

Если НайденныеСтроки.Количество() > 0 Тогда
    ЗаголовокИнформации = НСтр("ru = 'Выберите продавца!'");
    ТекстИнформации = НСтр("ru = 'В чеке присутствуют товары без указания продавца!'");
    ОбщегоНазначенияРТКлиент.ВывестиИнформациюДляРМКУправляемой(ЗаголовокИнформации, ТекстИнформации);
Иначе
    ОплатитьТовары("ФормаПростойОплаты");
КонецЕсли;

Важные рекомендации по встраиванию проверки в РМК

Обратим внимание на архитектурные нюансы конфигурации «1С:Розница»:

  1. Точка входа проверки: не следует размещать код валидации только в процедурах нажатия кнопок конкретных оплат (например, наличных или платежной карты). Кассир может использовать горячие клавиши или смешанную оплату. Правильнее размещать проверку в начале единой процедуры ОплатитьТовары() формы РМК.
  2. Использование расширений: чтобы не снимать конфигурацию с поддержки и избежать проблем при обновлении, проверку рекомендуется выносить в расширение конфигурации, перехватывая процедуру ОплатитьТовары() с директивой &Перед или &Вместо.
  3. Автоматическое заполнение: для ускорения работы кассиров имеет смысл настроить автоподстановку продавца по умолчанию при сканировании товара (из реквизита шапки или по авторизованному пользователю) либо считыванием персональной штрихкод-карты продавца-консультанта.
← На главную