- Создаем новый общий модуль (для удобства последующего обновления конфигурации).
- Создаем подписку на событие. Источники (документы по которым контролируем остатки). Событие - Обработка проведения. Обработчик - процедура в созданном общем модуле.
Процедура Ферма_КонтрольОстатковНеоперативноеПроведение(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Не Отказ И РежимЗаписи = РежимПроведенияДокумента.Неоперативный Тогда
МетаданныеДокумента = Источник.Ссылка.Метаданные();
// Заголовок для сообщений об ошибках проведения.
Заголовок = ОбщегоНазначения.ПредставлениеДокументаПриПроведении(Источник.Ссылка);
СтруктураШапкиДокумента = ОбщегоНазначения.СформироватьСтруктуруШапкиДокументаИПроверитьОтражениеВУчете(Источник, Отказ, Заголовок);
Если МетаданныеДокумента.Реквизиты.Найти("СкладОтправитель") <> Неопределено Тогда
СтруктураШапкиДокумента.Вставить("Склад", Источник.СкладОтправитель);
Иначе
СтруктураШапкиДокумента.Вставить("Склад", Источник.Склад);
КонецЕсли;
ИспользоватьРегистрСвободныеОстатки = глЗначениеПеременной("ИспользоватьРегистрСвободныеОстатки");
Если ИспользоватьРегистрСвободныеОстатки И НЕ Отказ Тогда
Если глЗначениеПеременной("ИспользоватьБлокировкуДанных") Тогда
Источник.Движения.СвободныеОстатки.БлокироватьДляИзменения = Истина;
КонецЕсли;
Источник.Движения.Записать();
Если МетаданныеДокумента.ТабличныеЧасти.Найти("Товары") <> Неопределено И Источник.Товары.Количество() <> 0 Тогда
Если Источник.Товары.Количество() <> 0 Тогда
КонтрольОстатков(
"Товары", СтруктураШапкиДокумента, Отказ, Заголовок, РежимПроведенияДокумента.Оперативный);
КонецЕсли;
КонецЕсли;
Если МетаданныеДокумента.ТабличныеЧасти.Найти("ВозвратнаяТара") <> Неопределено И Источник.ВозвратнаяТара.Количество() <> 0 Тогда
Если Источник.ВозвратнаяТара.Количество() <> 0 Тогда
КонтрольОстатков(
"ВозвратнаяТара", СтруктураШапкиДокумента, Отказ, Заголовок, РежимПроведенияДокумента.Оперативный);
КонецЕсли;
КонецЕсли;
Если МетаданныеДокумента.ТабличныеЧасти.Найти("Материалы") <> Неопределено И Источник.Материалы.Количество() <> 0 Тогда
Если Источник.Материалы.Количество() <> 0 Тогда
КонтрольОстатков(
"Материалы", СтруктураШапкиДокумента, Отказ, Заголовок, РежимПроведенияДокумента.Оперативный);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
3. Переносим процедуры модуля менеджера регистра накопления "Свободные остатки" в созданный общий модуль на первом этапе. И немного изменяем процедуру "КонтрольОстатков"
Процедура КонтрольОстатков(ИмяТабличнойЧасти, СтруктураШапкиДокумента, ОтказПроведения, ЗаголовокСообщения, РежимПроведения) Экспорт
Если РежимПроведения <> РежимПроведенияДокумента.Оперативный Тогда
Возврат;
КонецЕсли;
Если УправлениеДопПравамиПользователей.РазрешеноПревышениеОстаткаТоваровНаСкладе() Тогда
Возврат;
КонецЕсли;
Отказ = ОтказПроведения;
Заголовок = ЗаголовокСообщения;
СтруктураПараметров = ПолучитьСтруктуруПараметров(СтруктураШапкиДокумента, ИмяТабличнойЧасти, Заголовок);
Если СтруктураПараметров = Неопределено Тогда
Возврат;
КонецЕсли;
// Подготовим временную таблицу табличной части документа
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Если НЕ СформироватьВременнуюТаблицуПоТаблицеДокумента(МенеджерВременныхТаблиц, СтруктураПараметров) Тогда
// Нет номенклатуры, по которой необходимо контролировать остатки
Возврат;
КонецЕсли;
// Получим данные для передачи в процедуру ПроверитьОстатки()
ТекстЗапроса = "ВЫБРАТЬ
| ТаблицаОстатков.Склад КАК Склад,
| ТаблицаОстатков.Номенклатура КАК Номенклатура,
| ТаблицаОстатков.Номенклатура.ЕдиницаХраненияОстатков КАК ЕдиницаИзмерения,
| ТаблицаОстатков.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| ТаблицаОстатков.Номенклатура.ВестиУчетПоСериям КАК НоменклатураВестиУчетПоСериям,
| ТаблицаОстатков.Номенклатура.ВестиУчетПоХарактеристикам КАК НоменклатураВестиУчетПоХарактеристикам,
| ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка) КАК СерияНоменклатуры,
| ТаблицаОстатков.Качество КАК Качество,
| ТаблицаОстатков.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.СвободныеОстатки.Остатки(
| &ДокументКонтроля,
| (Склад, Номенклатура, ХарактеристикаНоменклатуры, Качество) В
| (ВЫБРАТЬ
| Таблица.Склад,
| Таблица.Номенклатура,
| Таблица.ХарактеристикаНоменклатуры,
| Таблица.Качество
| ИЗ
| ВременнаяТаблицаДокумента КАК Таблица)) КАК ТаблицаОстатков
|ГДЕ
| ТаблицаОстатков.КоличествоОстаток < 0";
Если СтруктураПараметров.ЕстьСерия Тогда
//Контроль остатков с учетом серии - отличия от предыдущего запроса помечены комментариями
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ
| ТаблицаОстатков.Склад КАК Склад,
| ТаблицаОстатков.Номенклатура КАК Номенклатура,
| ТаблицаОстатков.Номенклатура.ЕдиницаХраненияОстатков КАК ЕдиницаИзмерения,
| ТаблицаОстатков.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| ТаблицаОстатков.Номенклатура.ВестиУчетПоСериям КАК НоменклатураВестиУчетПоСериям,
| ТаблицаОстатков.Номенклатура.ВестиУчетПоХарактеристикам КАК НоменклатураВестиУчетПоХарактеристикам,
//серия - из документа
| ТаблицаОстатков.СерияНоменклатуры КАК СерияНоменклатуры,
| ТаблицаОстатков.Качество КАК Качество,
| ТаблицаОстатков.КоличествоСУчетомСерииОстаток КАК Количество
|ИЗ
| РегистрНакопления.СвободныеОстатки.Остатки(&ДокументКонтроля,
// остатки отбираются с учетом серии номенклатуры
| (Склад, Номенклатура, ХарактеристикаНоменклатуры, Качество, СерияНоменклатуры) В
| (ВЫБРАТЬ
| Таблица.Склад,
| Таблица.Номенклатура,
| Таблица.ХарактеристикаНоменклатуры,
| Таблица.Качество,
| Таблица.СерияНоменклатуры
| ИЗ
| ВременнаяТаблицаДокумента КАК Таблица
// учитывается только та номенклатура, по которой ведется учет по сериям
| ГДЕ Таблица.Номенклатура.ВестиУчетПоСериям
| )
| ) КАК ТаблицаОстатков
|
|ГДЕ
| ТаблицаОстатков.КоличествоСУчетомСерииОстаток < 0";
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("Ссылка", СтруктураПараметров.ДокументСсылка);
Запрос.УстановитьПараметр("ДокументКонтроля", Новый Граница(СтруктураПараметров.ДокументСсылка.МоментВремени()));
Запрос.Текст = ТекстЗапроса;
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
ПроверитьОстатки(Выборка, Отказ, Заголовок, СтруктураПараметров);
ОтказПроведения = Отказ;
ЗаголовокСообщения = Заголовок;
КонецПроцедуры // КонтрольОстатков()
Теперь, если у вас настроен контроль по регистру "Свободные остатки" и у роли пользователя нет разрешения проводить документы не контролируя остатки, документ не должен проводится при превышении остатка.