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