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

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

ШАБЛОНЫ КОДА

1. Функция расчета себестоимости из первой партии для списания. Аналогичная фукнция должна быть и для второй, третьей... на ваше усмотрение. Смотря сколько партий может быть списано при проведении одной расходной накладной. Мы посчитали что контроля двух парий списания будет достаточно.

Функция ЦенаССТПервойПартии (Номенклатура, Склад)

Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Склад", Ссылка.Склад);
Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1
| ПартииТоваровНаСкладахОстатки.Номенклатура КАК НоменклатураНаименование,
| ПартииТоваровНаСкладахОстатки.Склад,
| ЕСТЬNULL(ПартииТоваровНаСкладахОстатки.КоличествоОстаток, 1) КАК КоличествоОстаток,
| ЕСТЬNULL(ПартииТоваровНаСкладахОстатки.СтоимостьОстаток, 1) КАК СтоимостьОстаток,
| ПартииТоваровНаСкладахОстатки.ДокументОприходования КАК ДокументОприходования,
| ПартииТоваровНаСкладахОстатки.Номенклатура.Ссылка КАК Номенклатура,
| ПартииТоваровНаСкладахОстатки.СтоимостьОстаток / ПартииТоваровНаСкладахОстатки.КоличествоОстаток КАК ЦенаПартии
|ИЗ
| РегистрНакопления.ПартииТоваровНаСкладах.Остатки КАК ПартииТоваровНаСкладахОстатки
|ГДЕ
| ПартииТоваровНаСкладахОстатки.Номенклатура = &Номенклатура
| И ПартииТоваровНаСкладахОстатки.КоличествоОстаток > 0
| И ПартииТоваровНаСкладахОстатки.СтоимостьОстаток > 0
| И ПартииТоваровНаСкладахОстатки.Склад = &Склад
|
|УПОРЯДОЧИТЬ ПО
| ДокументОприходования";

Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Склад", Склад);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЦенаТовара = Выборка.ЦенаПартии;
КонецЦикла;

Возврат ЦенаТовара;

КонецФункции

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

Функция КолИзПервойПартии (Номенклатура, Склад)

Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Склад", Ссылка.Склад);

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1
| ПартииТоваровНаСкладахОстатки.Номенклатура КАК НоменклатураНаименование,
| ПартииТоваровНаСкладахОстатки.Склад,
| ЕСТЬNULL(ПартииТоваровНаСкладахОстатки.КоличествоОстаток, 1) КАК КоличествоОстаток,
| ЕСТЬNULL(ПартииТоваровНаСкладахОстатки.СтоимостьОстаток, 1) КАК СтоимостьОстаток,
| ПартииТоваровНаСкладахОстатки.ДокументОприходования КАК ДокументОприходования,
| ПартииТоваровНаСкладахОстатки.Номенклатура.Ссылка КАК Номенклатура,
| ПартииТоваровНаСкладахОстатки.СтоимостьОстаток / ПартииТоваровНаСкладахОстатки.КоличествоОстаток КАК ЦенаПартии
|ИЗ
| РегистрНакопления.ПартииТоваровНаСкладах.Остатки КАК ПартииТоваровНаСкладахОстатки
|ГДЕ
| ПартииТоваровНаСкладахОстатки.Номенклатура = &Номенклатура
| И ПартииТоваровНаСкладахОстатки.КоличествоОстаток > 0
| И ПартииТоваровНаСкладахОстатки.СтоимостьОстаток > 0
| И ПартииТоваровНаСкладахОстатки.Склад = &Склад
|
|УПОРЯДОЧИТЬ ПО
| ДокументОприходования";

Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Склад", Склад);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
КоличествоТовара = Выборка.КоличествоОстаток;
КонецЦикла;

Возврат КоличествоТовара;

КонецФункции

3. Опираясь на ранее созданную функцию проводим проверку при проведении документа в процедуре Обработка проведения

Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
КоличествоТовараИзДокумента =0;
КоличествоТовараИзПартии = 0;

Для Каждого Строка из Товары Цикл

КоличествоТовараИзДокумента = Строка.Количество;
КоличествоТовараИзПартии = КолИзПервойПартии(Строка.Номенклатура, Склад);

//если партий нужно проверять больше одной

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

РазницаМеждуССТиЦена = Формат(ЦенаТовараССТ - Строка.Цена,"ЧДЦ=2");
Сообщить ("Цена товара " + Строка.Номенклатура + " ниже себестоимости на:"+" "+РазницаМеждуССТиЦена +" грн.");
КонецЕсли;
КонецЕсли;

Если КоличествоТовараИзДокумента > КоличествоТовараИзПартии Тогда

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

РазницаМеждуССТиЦена = Формат(ЦенаТовараССТ2 - Строка.Цена,"ЧДЦ=2");
Сообщить ("Цена товара " + Строка.Номенклатура + " ниже себестоимости на:"+" "+РазницаМеждуССТиЦена +" грн.");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;