Как исправить ошибку «Не заполнена колонка "Документ продажи"» при возврате на основании Чека ККМ в УТ 11?

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

При работе в конфигурации 1С:Управление торговлей, редакция 11 (УТ 11) пользователи часто сталкиваются с неприятным поведением системы при попытке оформить документ Возврат товаров от клиента на основании ранее пробитого Чек ККМ. Программа выдает блокирующую ошибку: «Не заполнена колонка "Документ продажи" в строке X списка "Товары"». При этом визуально на форме документа такой колонки просто нет, что вводит операторов и кассиров в ступор.

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

Архитектурная причина ошибки: Чек ККМ против Отчета о розничных продажах

Чтобы понять природу этой ошибки, нам необходимо проанализировать, как устроена схема розничной торговли в семействе конфигураций ERP/КА/УТ. В системе существует разделение на оперативный учет продаж в течение дня и финансовый учет по итогам закрытия кассовой смены.

  1. Чек ККМ — это временный оперативный документ. Он предназначен для фиксации факта продажи конкретному покупателю «здесь и сейчас» и пробития фискального чека на ККТ. До закрытия смены эти документы делают движения по регистрам оперативного учета.
  2. Отчет о розничных продажах (ОРП) — это сводный финансовый документ, который формируется автоматически при закрытии кассовой смены. Он консолидирует в себе информацию обо всех пробитых за смену чеках. После проведения ОРП чеки ККМ архивируются. Именно ОРП является для системы конечным документом продажи, который формирует выручку, списывает себестоимость со склада и фиксирует валовую прибыль.

Когда мы пытаемся создать документ Возврат товаров от клиента с видом операции «Возврат от розничного покупателя», система ожидает, что для каждой возвращаемой товарной позиции будет четко определен финансовый документ продажи. Этим документом должен выступать именно Отчет о розничных продажах (или Реализация товаров и услуг, если продажа была оптовой), но никак не сам Чек ККМ.

На уровне метаданных в табличной части «Товары» документа возврата существует реквизит ДокументРеализации (в интерфейсе он называется «Документ продажи»). Однако на управляемой форме при розничной операции разработчики 1С скрыли эту колонку, чтобы упростить интерфейс для пользователя и заполнять её автоматически программными методами.

Анализ программного кода: почему реквизит остается пустым?

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


ДокументРеализации = РозничныеПродажи.ПолучитьОтчетОРозничныхПродажахПоЧекуККМ(ДокументОснование);

Для Каждого ТекСтрока Из ТаблицаТоваров Цикл
    Если ТекСтрока.ТипНоменклатуры = Перечисления.ТипыНоменклатуры.Товар 
       Или ТекСтрока.ТипНоменклатуры = Перечисления.ТипыНоменклатуры.МногооборотнаяТара Тогда
       
        НоваяСтрока = Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекСтрока);
        НоваяСтрока.ДокументРеализации = ДокументРеализации;
        
        НоваяСтрока.СпособОпределенияСебестоимости = ?(ЗначениеЗаполнено(НоваяСтрока.ДокументРеализации), 
            Перечисления.СпособыОпределенияСебестоимости.ИзДокументаПродажи, 
            Перечисления.СпособыОпределенияСебестоимости.ИзТекущегоДокумента);
            
    КонецЕсли;
КонецЦикла;

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

Почему помогает обходной путь с ручным подбором?

Пользователи на форумах часто отмечают, что если удалить все автоматически заполненные строки в документе возврата, а затем нажать кнопку «Заполнить» -> «Добавить товары из документов продажи» (или воспользоваться механизмом подбора), то документ успешно проводится. Выясним, почему так происходит.

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

Вариант решения №1: Корректировка методологии бизнес-процесса

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

  1. Возврат в течение той же кассовой смены (день в день):

    Использовать документ Возврат товаров от клиента в этом случае методологически неверно. Правильный путь — открыть Рабочее место кассира (РМК), выбрать операцию «Возврат» и пробить «Чек ККМ на возврат» на основании исходного чека продажи. При закрытии смены система автоматически свернет продажи и возвраты, сформировав корректный итоговый ОРП.

  2. Возврат после закрытия кассовой смены (в последующие дни):

    В этом сценарии использование документа Возврат товаров от клиента абсолютно оправдано. Однако создавать его целесообразно не на основании исходного Чека ККМ, а на основании сформированного Отчета о розничных продажах, в который этот чек вошел. Это гарантирует корректное автоматическое заполнение всех аналитик и цен.

Вариант решения №2: Исправление с помощью Расширения конфигурации (для программистов)

Если ваши бизнес-процессы требуют создания возвратов именно на основании чеков ККМ (например, при интеграции с внешними фронт-офисными системами) и конфигурация должна оставаться на поддержке, лучшим решением будет создание небольшого расширения конфигурации.

Мы можем применить два подхода в расширении:

Подход А. Вывод скрытой колонки на форму документа

Самое простое решение, не требующее написания сложного кода — сделать скрытую колонку видимой. Для этого в расширении находим форму документа ФормаДокументаВозвратТоваровОтКлиента, переносим элемент табличной части ТоварыДокументПродажи (или Товары.ДокументРеализации) на форму и настраиваем свойство видимости. Если автозаполнение не сработает, пользователь сможет вручную выбрать нужный ОРП прямо в строке табличной части.

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

Мы можем перехватить процедуру заполнения документа возврата на основании Чека ККМ с помощью аннотации &После или &Вместо. Наша задача — научить систему искать документ-продажи более надежным способом, либо, если смена еще не закрыта, временно подставлять сам чек в качестве документа продажи (хотя для полноценного проведения по регистрам себестоимости всё же потребуется ОРП).

Рассмотрим пример кода для расширения модуля менеджера документа ВозвратТоваровОтКлиента:


&После("ЗаполнитьПоЧекуККМ")
Процедура Расш_ЗаполнитьПоЧекуККМ(ДокументОснование)
    
    // Проверим, заполнена ли колонка ДокументРеализации в строках
    Для Каждого СтрокаТовара Из ЭтотОбъект.Товары Цикл
        
        Если Не ЗначениеЗаполнено(СтрокаТовара.ДокументРеализации) Тогда
            
            // Попробуем альтернативный поиск ОРП через запрос к регистру сведений "НоменклатураДокументовПретензий"
            // или напрямую через запрос к табличным частям существующих Отчетов о розничных продажах
            НайденныйОРП = ПолучитьОРПАльтернативнымПутем(ДокументОснование);
            
            Если ЗначениеЗаполнено(НайденныйОРП) Тогда
                СтрокаТовара.ДокументРеализации = НайденныйОРП;
                СтрокаТовара.СпособОпределенияСебестоимости = Перечисления.СпособыОпределенияСебестоимости.ИзДокументаПродажи;
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

&НаСервере
Функция ПолучитьОРПАльтернативнымПутем(ЧекСсылка)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗЛИЧНЫЕ
        |   ОРПТовары.Ссылка КАК Ссылка
        |ИЗ
        |   Документ.ОтчетОРозничныхПродажах.Товары КАК ОРПТовары
        |ГДЕ
        |   ОРПТовары.ДокументОбъект = &ЧекСсылка"; // Или иная связь в зависимости от релиза
        
    Запрос.УстановитьПараметр("ЧекСсылка", ЧекСсылка);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    Возврат Неопределено;
    
КонецФункции

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

← На главную