При работе с конфигурацией 1С:Торговля и Склад 7.7, особенно в ее более поздних релизах (начиная примерно с 7.70.973), пользователи могут столкнуться со специфической, но критичной ошибкой в документе ИнвентаризацияТМЦ. Эта ошибка проявляется в некорректном пересчете фактической суммы при изменении номенклатуры в уже заполненной строке табличной части документа, в результате чего возникает несоответствие между фактическим количеством и фактической суммой. Давайте разберем эту проблему подробно и предложим готовое решение.
Мы выяснили, что в определенный момент (примерно между релизами 7.70.935 и 7.70.973) разработчики 1С закомментировали одну из ключевых строк кода в процедуре ЗаполнитьРеквСтрокиПоСкладу() модуля формы документа ИнвентаризацияТМЦ. Эта строка отвечала за первоначальное присвоение фактического количества значению учетного количества. Хотя это изменение, возможно, преследовало благие цели (например, чтобы пользователь всегда вводил фактическое количество вручную), оно было реализовано некорректно.
Основная проблема заключается в следующем: если строка, присваивающая Количество (фактическое) значению КоличествоУчет (учетное) была закомментирована, то при последующем изменении номенклатуры в строке документа, реквизит Количество (фактическое) сохраняет свое старое значение от предыдущей номенклатуры. При этом пересчет фактической суммы происходит исходя из *учетной* суммы и *учетного* количества новой номенклатуры, а не на основании фактического количества, которое "зависло". В итоге, мы можем получить ситуацию, когда есть отклонение по количеству, но при этом отклонения по сумме нет, так как сумма была приравнена к учетной.
Это приводит к логическому несоответствию, о котором пользователи, как правило, сообщают, обнаружив расхождения в отчетах. При штатной работе такая ситуация возникает редко, поскольку требует довольно нелогичных действий пользователя, но она вполне воспроизводима и является ошибкой системы.
Чтобы убедиться в наличии описанной проблемы, мы можем воспроизвести ее, следуя следующему алгоритму:
ИнвентаризацияТМЦ.КоличествоУчет (учетное количество), например, 10 штук.Количество (фактическое количество), например, 12 штук.СуммаУчет и Сумма.КоличествоУчет, например, 5 штук.Количество, например, 5 штук. (В данном случае отклонений нет, суммы должны быть равны).После выполнения этих действий мы увидим следующую картину в первой строке:
КоличествоУчет: 5 (корректно)Количество (фактическое): 12 (некорректно, "зависло" от предыдущего Товар1)СуммаУчет: Будет рассчитана от 5 штук Товар2.Сумма (фактическая): Будет также приравнена к СуммаУчет от 5 штук Товар2, хотя фактическое количество указано 12.Таким образом, возникает несоответствие: при фактическом количестве в 12 штук (Товар2), система показывает фактическую сумму, соответствующую 5 штукам Товар2. Эта ошибка будет сохраняться до тех пор, пока мы вручную не изменим фактическое количество или цену в этой строке.
Давайте посмотрим на участок кода в процедуре ЗаполнитьРеквСтрокиПоСкладу() модуля формы документа Документ.ИнвентаризацияТМЦ, где кроется причина проблемы. Этот код был обнаружен в типовой конфигурации, включая релиз 1002 и более ранние, такие как 973, 974, 975.
Первоначальный проблемный участок кода выглядел примерно так (с закомментированной строкой):
Процедура ЗаполнитьРеквСтрокиПоСкладу()
// ... прочий код ...
Если ТаблОстатков.КоличествоСтрок() > 0 Тогда
ТаблОстатков.ПолучитьСтрокуПоНомеру(1);
Единица = Номенклатура.БазоваяЕдиница;
Коэффициент = Единица.Коэффициент;
КоличествоУчет = ТаблОстатков.Количество;
//Количество = ТаблОстатков.Количество; // ЗЛОП тут собака порылась какая-то сука
// Эта строка была закомментирована!
НомСтр = 0;
Если ТаблСуммы.НайтиЗначение(Номенклатура,НомСтр,"Номенклатура") = 1 Тогда
ТаблСуммы.ПолучитьСтрокуПоНомеру(НомСтр);
Если ТаблСуммы.Количество <> 0 Тогда
ВремСумма = ТаблСуммы.СуммаБезНДС * КоличествоУчет / ТаблСуммы.Количество;
СуммаУчет = глПересчет(ВремСумма, глРубли, ДатаДок, Валюта, Курс,, Кратность);
Иначе
СуммаУчет = 0;
КонецЕсли;
Иначе
СуммаУчет = 0;
КонецЕсли;
// ЗЛОП было
//Сумма = СуммаУчет;
//Цена = ?(КоличествоУчет = 0,0, СуммаУчет / КоличествоУчет);
// ЗЛОП стало (как предлагается исправить)
// Цена = ?(КоличествоУчет = 0,0, СуммаУчет / КоличествоУчет);
// Сумма = ?(Количество = КоличествоУчет, СуммаУчет, Цена * Количество);
КонецЕсли;
// ... прочий код ...
КонецПроцедуры // ЗаполнитьРеквСтрокиПоСкладу()
Как мы видим, строка Количество = ТаблОстатков.Количество; была закомментирована. Это означает, что при перевыборе номенклатуры фактическое количество в строке не обновлялось из учетных данных, оставаясь "зависшим" от предыдущей номенклатуры. При этом блок расчета Сумма и Цена также содержит ошибку в логике после этого изменения.
Для исправления этой ошибки нам необходимо внести две ключевые модификации:
Предлагаемое исправление кода выглядит следующим образом:
Процедура ЗаполнитьРеквСтрокиПоСкладу()
Перем ТаблСуммы, ТаблОстатков;
Перем СписТоваров;
СписТоваров = СоздатьОбъект("СписокЗначений");
СписТоваров.ДобавитьЗначение(Номенклатура);
ПолучитьОстатки(СписТоваров, 0, ТаблОстатков, ТаблСуммы);
ТаблОстатков.Свернуть("Номенклатура", "Количество");
ТаблСуммы.Свернуть("Номенклатура","Количество,СуммаБезНДС");
Если ТаблОстатков.КоличествоСтрок() > 0 Тогда
ТаблОстатков.ПолучитьСтрокуПоНомеру(1);
Единица = Номенклатура.БазоваяЕдиница;
Коэффициент = Единица.Коэффициент;
КоличествоУчет = ТаблОстатков.Количество;
Количество = ТаблОстатков.Количество; // ВОТ ЭТА СТРОКА ДОЛЖНА БЫТЬ АКТИВНА ИЛИ ДОБАВЛЕНА
// Мы устанавливаем фактическое количество равным учетному
НомСтр = 0;
Если ТаблСуммы.НайтиЗначение(Номенклатура,НомСтр,"Номенклатура") = 1 Тогда
ТаблСуммы.ПолучитьСтрокуПоНомеру(НомСтр);
Если ТаблСуммы.Количество <> 0 Тогда
ВремСумма = ТаблСуммы.СуммаБезНДС * КоличествоУчет / ТаблСуммы.Количество;
СуммаУчет = глПересчет(ВремСумма, глРубли, ДатаДок, Валюта, Курс,, Кратность);
Иначе
СуммаУчет = 0;
КонецЕсли;
Иначе
СуммаУчет = 0;
КонецЕсли;
// Здесь мы меняем логику расчета фактической Суммы
Цена = ?(КоличествоУчет = 0,0, СуммаУчет / КоличествоУчет); // Цена считается на базе учетных данных
Сумма = ?(Количество = КоличествоУчет, СуммаУчет, Цена * Количество); // Фактическая сумма пересчитывается
// исходя из фактического количества и рассчитанной цены
КонецЕсли;
КонецПроцедуры // ЗаполнитьРеквСтрокиПоСкладу()
В чем суть изменений?
Количество = ТаблОстатков.Количество; теперь активна. Это гарантирует, что при выборе новой номенклатуры в строке, ее фактическое количество (реквизит Количество в табличной части) будет инициализировано значением из учетных данных (КоличествоУчет). Таким образом, мы избегаем "зависания" старого значения.Сумма изменена. Сначала рассчитывается Цена на основании СуммаУчет и КоличествоУчет. Затем, Сумма (фактическая) рассчитывается с учетом двух сценариев:
Количество (фактическое) равно КоличествоУчет, то Сумма приравнивается к СуммаУчет. Это логично, если отклонений нет.Количество (фактическое) отличается от КоличествоУчет, то Сумма рассчитывается как Цена * Количество. Это позволяет корректно получить фактическую сумму на основании фактического количества, даже если оно отличается от учетного.Такой подход обеспечивает корректное отображение фактических данных и их сумм, предотвращая описанное логическое несоответствие.
Чтобы лучше понять значимость этого исправления, давайте рассмотрим общий контекст работы с документом Инвентаризация ТМЦ в 1С:Торговля и Склад 7.7 и типичные проблемы, с которыми сталкиваются пользователи.
Документ Акт инвентаризации ТМЦ предназначен для сопоставления фактических остатков товаров на складе с учетными данными, хранящимися в информационной базе. Его основная задача — выявить излишки или недостачи и стать основанием для их дальнейшего оприходования или списания. Обычно процесс выглядит так: после автоматического заполнения учетных остатков, фактическое количество вводится вручную, и на основе этого остальные графы, включая суммы и отклонения, должны рассчитываться автоматически.
Частой проблемой в 1С 7.7 является расхождение между Количеством (учетным) в документе инвентаризации и данными оборотно-сальдовой ведомости (ОСВ) по счету 41 "Товары" или формой "Остатки товаров". Нередко это происходит из-за неуказанного склада в документе, поскольку остатки могут быть в разрезе складов. Проблему часто решают, добавив поле Склад в форму документа и корректно перезаполнив его.
Графа Количество (факт) по умолчанию заполняется на основе бухгалтерского учета. При наличии расхождений с реальным наличием ТМЦ, пользователю, как правило, необходимо вручную внести корректировки. Других автоматических вариантов для массового изменения фактического количества обычно не предусмотрено, что делает каждое такое расхождение объектом внимательного ручного контроля.
Важным историческим моментом является изменение в релизе 7.70.938 от 15.04.2005, где было исправлено поведение кнопки "Заполнить". Теперь она заполняет только колонку Количество (учетное), и был добавлен отдельный вариант заполнения — "Заполнить фактическое количество по учетному". Это свидетельствует о том, что разработчики 1С неоднократно пересматривали логику заполнения этих полей, что могло привести к появлению или рецидиву подобных багов.
В некоторых случаях, хотя в данном обсуждении речь идет о 7.7, и эта аналогия больше применима к более сложным конфигурациям вроде "Комплексной автоматизации" в 8-й версии, могут возникать расхождения сумм в документе инвентаризации и ОСВ, связанные с документами пересчета себестоимости. Например, при использовании методов средней взвешенной себестоимости или ФИФО, цена единицы товара может меняться задним числом, что приводит к необходимости перепроведения документов или пересчета. В 1С 7.7 также присутствуют механизмы расчета себестоимости, и их некорректная работа или особенности могли косвенно влиять на суммы в инвентаризации, если базовые цены были рассчитаны неверно.
Если фактическое количество товара превышает учетное, документ инвентаризации может не проводиться, что препятствует дальнейшему списанию или оприходованию излишков. В таких случаях необходимо убедиться, что фактическое количество корректно указано в документе инвентаризации и произведены необходимые действия по корректировке (например, оприходование излишков), чтобы система могла списать или оприходовать товары с учетом фактического наличия.
Критически важно помнить, что официальная поддержка 1С:Предприятия 7.7 была прекращена с 2003 года, хотя ограниченные обновления форм отчетности продолжали выходить. Это означает, что новые функциональные изменения или исправления подобных ошибок в типовых конфигурациях уже не выпускаются. Поэтому, любые найденные баги, такие как тот, что мы рассмотрели, требуют самостоятельной доработки конфигурации силами программистов или квалифицированных пользователей. Предложенное нами исправление как раз является таким решением, позволяющим решить конкретную проблему в устаревшей, но все еще используемой системе.
Таким образом, описанная ошибка, хотя и является специфическим багом, возникающим при определенных, не самых очевидных действиях пользователя, серьезно нарушает логику учета и требует внимания. Применение предложенной модификации кода позволяет восстановить корректное поведение документа ИнвентаризацияТМЦ и обеспечить точность данных.