Ошибка проведения документа 1С выглядит одинаково при любой причине: окно «Не удалось провести…», иногда — «Операция не выполнена» без пояснений. А причин с десяток: не хватает остатков, документ попал в закрытый период, у пользователя нет прав, не заполнен реквизит, упала доработка или подписка на событие. Ниже — как по тексту понять класс ошибки, где прочитать её полностью и как кодом найти модуль, на котором проведение сорвалось.
Встречается это везде, где документ записывается в режиме проведения: кнопка «Провести», групповое перепроведение, загрузка из обмена, регламентные задания. Любой обработчик — модуль объекта, подписка, расширение — может выставить Отказ = Истина или вызвать исключение, и платформа откатит транзакцию целиком: в регистрах не останется ни одной записи.
Окно «Не удалось провести» говорит лишь, что 1С не удалось провести документ. Причину пишет обработчик, который отказал, — в окно сообщений под формой документа. Если сообщений нет, а появилось окно ошибки, смотрите исключение: кнопка «Подробно» показывает его полный текст.
| Текст сообщения | Что случилось | Что делать |
|---|---|---|
| «Недостаточно товара в наличии на складе …», «Превышен доступный остаток товара на складе …» (УТ 11.4) | Контроль остатков после записи движений: товара на момент документа меньше, чем в документе, или он в резерве | Остатки на дату и время документа, резервы, проведено ли поступление; флажок склада «Контролировать обеспечение» (в 11.5 — «Контролировать свободные остатки») |
| «Превышен оперативный складской остаток на складе …» (УТ 11.4) | Не хватает товара по оперативному складскому учёту | Расходные ордера, серии; флажок склада «Контролировать оперативные остатки» |
| «Запрещено изменять данные с датой ранее … (включительно)» | Дата запрета изменения БСП: период закрыт | Дату — общую или для пользователя — настраивает администратор, путь ниже |
| «Недостаточно прав для проведения», «Нарушение прав доступа!», «У пользователя недостаточно прав на исполнение операции над базой данных» | Нет права на документ или регистр либо сработало ограничение на уровне записей | Профиль пользователя; разбор — в статье про нарушение прав доступа |
| «Поле "…" не заполнено», «Не заполнена колонка "…" в строке N списка "…"» | Проверка заполнения перед проведением | Заполнить поле; если оно обязательно не всегда — править ОбработкаПроверкиЗаполнения |
| «Помеченный на удаление документ не может быть проведен!» | На документе пометка удаления | Снять пометку |
| «Дата оперативно проводимого документа больше текущей…» или «…меньше текущей» | Документ проводится оперативно, а его дата не текущая | Провести неоперативно (платформа предложит) или поправить дату |
| «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных…» | Документ изменили в другом сеансе или кодом, пока была открыта форма | Закрыть форму без сохранения, открыть и провести заново |
| «Конфликт блокировок при выполнении транзакции:», «Превышено максимальное время ожидания предоставления блокировки» | Те же данные одновременно пишет другой сеанс | Повторить; если часто — разбирать блокировки |
| «{ОбщийМодуль.Имя.Модуль(245)}: …», «Поле объекта не обнаружено (…)», «Значение не является значением объектного типа (…)», «Деление на 0» | Ошибка в коде: доработка, подписка, расширение | Модуль и строка — в подробном тексте, разбор ниже |
| «В данной транзакции уже происходили ошибки!» | Раньше в той же транзакции перехватили исключение и продолжили работу | Искать первую ошибку цепочки, а не эту |
| «Операция не выполнена!» без сообщений | Обработчик выставил Отказ = Истина и ничего не сообщил | Найти обработчик по списку участников проведения (листинг 3) |
{Документ.Имя.МодульОбъекта(120)}: исходная строка кода, а после «по причине:» идёт вложенная ошибка. Читайте снизу: последняя причина — место, где исключение возникло, верхние строки — путь к нему.Если ошибка плавает или окно уже закрыли, воспроизведите проведение кодом. Функция ниже проводит документ так же, как форма, но в транзакции с откатом: база не меняется, а на выходе — сообщения обработчиков, подробный текст и цепочка модулей. Код рассчитан на модуль объекта внешней обработки (как её создать), подойдёт и серверный общий модуль.
// Модуль объекта внешней обработки «ДиагностикаПроведения» (подойдёт и общий
// модуль с флагом «Сервер»). Проводит документ так же, как форма: сначала
// проверка заполнения, потом запись в режиме проведения. Возвращает то, чего
// не видно в окне «Не удалось провести»: сообщения обработчиков, подробный
// текст исключения и цепочку модулей со строками.
// ТолькоПроверить = Истина: проведение в транзакции с откатом, база не меняется.
// Внешние действия обработчиков (HTTP-запросы, письма, файлы) откат не отменяет.
Функция ПровестиСДиагностикой(ДокументСсылка, ТолькоПроверить = Истина) Экспорт
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Диагностику проведения запускают вне транзакции.";
КонецЕсли;
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
Если ДокументОбъект = Неопределено Тогда
ВызватьИсключение "Документ не найден в базе: " + Строка(ДокументСсылка);
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Успешно", Ложь);
Результат.Вставить("Этап", "Проверка заполнения");
Результат.Вставить("Сообщения", Новый Массив);
Результат.Вставить("ТекстОшибки", "");
Результат.Вставить("Цепочка", Новый Массив);
// Сбросить сообщения, накопленные сеансом раньше: соберём только свои
ПолучитьСообщенияПользователю(Истина);
НачатьТранзакцию();
Попытка
// Форма проверяет заполнение перед проведением, программная запись - нет.
// Проверка внутри Попытка: ошибка в ОбработкаПроверкиЗаполнения тоже попадёт в отчёт.
Если ДокументОбъект.ПроверитьЗаполнение() Тогда
Результат.Этап = "Проведение";
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Результат.Успешно = Истина;
КонецЕсли;
Если ТолькоПроверить Или Не Результат.Успешно Тогда
ОтменитьТранзакцию();
Иначе
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
ОтменитьТранзакцию();
Результат.Успешно = Ложь;
Инфо = ИнформацияОбОшибке();
// ОбработкаОшибок - с 8.3.17; на старых платформах ПодробноеПредставлениеОшибки(Инфо)
Результат.ТекстОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(Инфо);
Результат.Цепочка = ЦепочкаОшибки(Инфо);
КонецПопытки;
// Причины отказа обработчики пишут сообщениями: остатки, даты запрета, поля
Для Каждого Сообщение Из ПолучитьСообщенияПользователю(Истина) Цикл
Текст = СокрЛП(Сообщение.Текст);
Если ЗначениеЗаполнено(Сообщение.Поле) Тогда
Текст = Текст + " [поле: " + Сообщение.Поле + "]";
КонецЕсли;
Результат.Сообщения.Добавить(Текст);
КонецЦикла;
Если Не Результат.Успешно Тогда
ЗаписьЖурналаРегистрации("Диагностика проведения", УровеньЖурналаРегистрации.Ошибка,
ДокументСсылка.Метаданные(), ДокументСсылка,
СтрСоединить(Результат.Сообщения, Символы.ПС) + Символы.ПС + Результат.ТекстОшибки);
КонецЕсли;
Возврат Результат;
КонецФункции
// Разворачивает цепочку «по причине:» от внешнего вызова (Записать) до места,
// где исключение возникло. Последний уровень с модулем - обычно виновник.
Функция ЦепочкаОшибки(Знач Инфо) Экспорт
Цепочка = Новый Массив;
Пока Инфо <> Неопределено Цикл
Уровень = Новый Структура("Модуль, НомерСтроки, ИсходнаяСтрока, Описание",
Инфо.ИмяМодуля, Инфо.НомерСтроки, СокрЛП(Инфо.ИсходнаяСтрока), Инфо.Описание);
Цепочка.Добавить(Уровень);
Инфо = Инфо.Причина;
КонецЦикла;
Возврат Цепочка;
КонецФункции
ПроверитьЗаполнение(). Форма перед проведением сама вызывает проверку заполнения, программная запись — нет. Без этого шага диагностика не увидит «Поле … не заполнено».НачатьТранзакцию() и ОтменитьТранзакцию(). При ТолькоПроверить = Истина проведение проходит целиком — движения, контроль остатков, подписки — и откатывается. Внешние действия обработчиков (отправку заказа на сайт, письмо) откат не вернёт.ПолучитьСообщенияПользователю(Истина). На сервере забирает сообщения обработчиков, в том числе отправленные через ОбщегоНазначения.СообщитьПользователю. Первый вызов чистит старые сообщения сеанса, второй собирает свои.ОбработкаОшибок.ПодробноеПредставлениеОшибки. Тот же текст, что по кнопке «Подробно»; глобальная функция с таким именем с 8.3.17 не рекомендуется.ЦепочкаОшибки. Проходит по Причина до конца: первый уровень — вызов Записать, последний с модулем — строка, где ошибка возникла.ЗаписьЖурналаРегистрации. Неудачная попытка остаётся в журнале регистрации событием «Диагностика проведения» с документом в колонке «Данные».Часть причин видна без попытки провести. Функция проверяет их для текущего пользователя или для сотрудника, у которого документ не проводится: под администратором ошибки прав не воспроизводятся.
// Модуль объекта обработки (продолжение). Причины, которые видны без проведения.
// Пользователь - ПользовательИнформационнойБазы, у которого документ
// не проводится; Неопределено - текущий. Чужие права проверяет администратор.
Функция ПричиныДоПроведения(ДокументСсылка, Пользователь = Неопределено) Экспорт
Причины = Новый Массив;
МетаданныеДокумента = ДокументСсылка.Метаданные();
Если МетаданныеДокумента.Проведение <> Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда
Причины.Добавить("Проведение документов этого вида запрещено в конфигурации.");
Возврат Причины;
КонецЕсли;
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
Если ДокументОбъект = Неопределено Тогда
Причины.Добавить("Документа нет в базе: ссылка битая.");
Возврат Причины;
КонецЕсли;
Если ДокументОбъект.ПометкаУдаления Тогда
Причины.Добавить("Документ помечен на удаление: платформа его не проведёт.");
КонецЕсли;
// Права на документ. Без «ИнтерактивноеИзменениеПроведенных» проведённый
// документ открывается только для просмотра - перепровести его из формы нельзя.
ИменаПрав = СтрРазделить("Проведение,ИнтерактивноеПроведение", ",");
Если ДокументОбъект.Проведен Тогда
ИменаПрав.Добавить("ИнтерактивноеИзменениеПроведенных");
КонецЕсли;
Для Каждого ИмяПрава Из ИменаПрав Цикл
Если Не ЕстьПраво(ИмяПрава, МетаданныеДокумента, Пользователь) Тогда
Причины.Добавить(СтрШаблон("Нет права «%1» на документ «%2».",
ИмяПрава, МетаданныеДокумента.Представление()));
КонецЕсли;
КонецЦикла;
// Права на регистры движений. Если код пишет регистр в привилегированном
// режиме, право не нужно: строка - повод проверить, а не приговор.
Для Каждого Регистр Из МетаданныеДокумента.Движения Цикл
Если Не ЕстьПраво("Изменение", Регистр, Пользователь) Тогда
Причины.Добавить(СтрШаблон("Нет права «Изменение» на %1: возможна ошибка «Нарушение прав доступа!».",
Регистр.ПолноеИмя()));
КонецЕсли;
КонецЦикла;
// Дата запрета изменения БСП (сверено по УТ 11.4 и КА 2.5). Проверяется
// по данным самого документа и для текущего сеанса; движения регистров
// проверит подписка при проведении.
Если Метаданные.ОбщиеМодули.Найти("ДатыЗапретаИзменения") <> Неопределено Тогда
// Так же делает подписка БСП перед записью документа
ДокументОбъект.ДополнительныеСвойства.Вставить("РежимЗаписи", РежимЗаписиДокумента.Проведение);
ОписаниеЗапрета = "";
МодульДатЗапрета = ОбщегоНазначения.ОбщийМодуль("ДатыЗапретаИзменения");
Если МодульДатЗапрета.ИзменениеЗапрещено(ДокументОбъект, , ОписаниеЗапрета) Тогда
Причины.Добавить(ОписаниеЗапрета);
КонецЕсли;
КонецЕсли;
Возврат Причины;
КонецФункции
// ПравоДоступа для текущего пользователя или для указанного.
Функция ЕстьПраво(ИмяПрава, ОбъектМетаданных, Пользователь)
Если Пользователь = Неопределено Тогда
Возврат ПравоДоступа(ИмяПрава, ОбъектМетаданных);
КонецЕсли;
Возврат ПравоДоступа(ИмяПрава, ОбъектМетаданных, Пользователь);
КонецФункции
Дата запрета в БСП бывает общей, по разделу или объекту, а также для отдельного пользователя или группы — поэтому у бухгалтера документ проводится, а у менеджера нет. Настраивает даты администратор: в УТ 11.4 — «НСИ и администрирование → Настройки пользователей и прав», группа «Даты запрета изменения», ссылка «Настроить». Отключать проверку кодом (ДатыЗапретаИзменения.ОтключитьПроверкуДатЗапрета) ради одного документа не стоит: отключение действует на весь сеанс и требует полных прав или привилегированного режима.
Имя модуля в подробном тексте говорит, где код: Документ.Имя.МодульОбъекта — модуль документа, ОбщийМодуль.Имя.Модуль — общий модуль, часто обработчик подписки. Но модуль документа — не единственный участник: при записи вызываются подписки на сам документ и на наборы записей каждого регистра из его движений, а расширения перехватывают типовые методы аннотациями &Перед, &После, &Вместо, &ИзменениеИКонтроль. Функции ниже определяют владельца модуля и перечисляют участников проведения.
// Модуль объекта обработки (продолжение). Чей модуль из цепочки ошибки:
// «ОбщийМодуль.Имя.Модуль», «Документ.Имя.МодульОбъекта» и т. п.
Функция ЧейМодуль(ИмяМодуля) Экспорт
Части = СтрРазделить(ИмяМодуля, ".");
Если Части.Количество() < 3 Тогда
Возврат "не модуль конфигурации";
КонецЕсли;
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(Части[0] + "." + Части[1]);
Если ОбъектМетаданных = Неопределено Тогда
Возврат "нет в метаданных: внешняя обработка или отчёт";
КонецЕсли;
Расширение = ОбъектМетаданных.РасширениеКонфигурации();
Если Расширение <> Неопределено Тогда
Возврат "объект расширения «" + Расширение.Имя + "»";
ИначеЕсли ОбъектМетаданных.ЕстьИзмененияРасширениямиКонфигурации() Тогда
Возврат "конфигурация, объект изменён расширением: смотрите модуль и в расширении";
КонецЕсли;
Возврат "основная конфигурация";
КонецФункции
// Всё, что работает при проведении помимо модуля объекта документа:
// подписки на документ и на наборы записей его регистров, расширения сеанса.
Функция УчастникиПроведения(МетаданныеДокумента) Экспорт
Строки = Новый Массив;
Если МетаданныеДокумента.ЕстьИзмененияРасширениямиКонфигурации() Тогда
Строки.Добавить("Документ изменён расширением: его модули есть и в расширении.");
КонецЕсли;
// Источники подписок: объект документа и наборы записей регистров движений
Источники = Новый Соответствие;
Источники.Вставить(Тип("ДокументОбъект." + МетаданныеДокумента.Имя), "документ");
Для Каждого Регистр Из МетаданныеДокумента.Движения Цикл
// «РегистрНакопления.Имя» -> тип «РегистрНакопленияНаборЗаписей.Имя»
ИмяТипаНабора = СтрЗаменить(Регистр.ПолноеИмя(), ".", "НаборЗаписей.");
Источники.Вставить(Тип(ИмяТипаНабора), Регистр.ПолноеИмя());
Если Регистр.ЕстьИзмененияРасширениямиКонфигурации() Тогда
Строки.Добавить(Регистр.ПолноеИмя() + " изменён расширением.");
КонецЕсли;
КонецЦикла;
Для Каждого Подписка Из Метаданные.ПодпискиНаСобытия Цикл
Для Каждого Элемент Из Источники Цикл
Если Подписка.Источник.СодержитТип(Элемент.Ключ) Тогда
Расширение = Подписка.РасширениеКонфигурации();
Строки.Добавить(СтрШаблон("Подписка %1 (%2): %3%4", Подписка.Имя, Подписка.Синоним,
Элемент.Значение, ?(Расширение = Неопределено, "", ", расширение " + Расширение.Имя)));
Прервать; // подписку и на документ, и на регистры показываем один раз
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Расширения, подключённые в этом сеансе. Без административных прав
// список может быть недоступен - тогда в отчёте будет строка с причиной.
Попытка
Расширения = РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные);
Исключение
Расширения = Новый Массив;
Строки.Добавить("Список расширений недоступен: "
+ ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Для Каждого Расширение Из Расширения Цикл
Строки.Добавить(СтрШаблон("Расширение %1 «%2», версия %3",
Расширение.Имя, Расширение.Синоним, Расширение.Версия));
КонецЦикла;
Возврат Строки;
КонецФункции
У отказа без исключения цепочки нет, и список участников становится планом поиска: точки останова — на строки Отказ = Истина в найденных модулях. В УТ 11.4 дату запрета проверяют подписки БСП ПроверитьДатуЗапретаИзмененияПередЗаписьюДокумента и ПроверитьДатуЗапретаИзмененияПередЗаписьюНабораЗаписей, а остатки — ПроведениеСерверУТ.ВыполнитьКонтрольРезультатовПроведения в конце ОбработкаПроведения документа. Как устроены подписки — в статье про подписки на события.
Форма собирает три функции в один отчёт. Создайте реквизиты в редакторе формы, поле «Результат» сделайте многострочным, функции листингов 1–3 положите в модуль объекта обработки. Запускайте под администратором: права другого пользователя без административных прав не проверить, а список расширений может быть недоступен.
// Модуль управляемой формы внешней обработки «ДиагностикаПроведения».
// Реквизиты формы: Документ (ДокументСсылка - любой документ), ТолькоПроверить
// (Булево), ИмяПользователя (Строка), Результат (Строка, многострочное поле).
// Команда формы Проверить. Функции листингов 1-3 - в модуле объекта обработки.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ТолькоПроверить = Истина;
КонецПроцедуры
&НаКлиенте
Процедура Проверить(Команда)
Если Не ЗначениеЗаполнено(Документ) Тогда
ПоказатьПредупреждение(, "Выберите документ.");
Возврат;
КонецЕсли;
Результат = ПроверитьНаСервере();
КонецПроцедуры
&НаСервере
Функция ПроверитьНаСервере()
Обработка = РеквизитФормыВЗначение("Объект");
Строки = Новый Массив;
// Сотрудник, у которого документ не проводится (нужны права администратора)
Пользователь = Неопределено;
Если ЗначениеЗаполнено(ИмяПользователя) Тогда
Пользователь = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
Если Пользователь = Неопределено Тогда
Возврат "Пользователь не найден: " + ИмяПользователя;
КонецЕсли;
КонецЕсли;
Строки.Добавить("1. Без проведения");
Для Каждого Причина Из Обработка.ПричиныДоПроведения(Документ, Пользователь) Цикл
Строки.Добавить(" " + Причина);
КонецЦикла;
// Проведение выполняется от текущего пользователя
Итог = Обработка.ПровестиСДиагностикой(Документ, ТолькоПроверить);
Если Итог.Успешно Тогда
ТекстИтога = ?(ТолькоПроверить, "прошло, изменения отменены", "документ проведён");
Иначе
ТекстИтога = "ошибка";
КонецЕсли;
Строки.Добавить(СтрШаблон("2. %1: %2", Итог.Этап, ТекстИтога));
Для Каждого Текст Из Итог.Сообщения Цикл
Строки.Добавить(" Сообщение: " + Текст);
КонецЦикла;
Для Каждого Уровень Из Итог.Цепочка Цикл
Если ЗначениеЗаполнено(Уровень.Модуль) Тогда
Строки.Добавить(СтрШаблон(" %1, строка %2 (%3): %4", Уровень.Модуль,
XMLСтрока(Уровень.НомерСтроки), Обработка.ЧейМодуль(Уровень.Модуль), Уровень.ИсходнаяСтрока));
КонецЕсли;
Строки.Добавить(" " + Уровень.Описание);
КонецЦикла;
Строки.Добавить("3. Кто ещё участвует в проведении");
Для Каждого Участник Из Обработка.УчастникиПроведения(Документ.Метаданные()) Цикл
Строки.Добавить(" " + Участник);
КонецЦикла;
Возврат СтрСоединить(Строки, Символы.ПС);
КонецФункции
Проведение выполняется от текущего пользователя, поэтому права сотрудника проверяет только первый блок. Персональную дату запрета и ограничения на уровне записей покажет запуск под учётной записью сотрудника с пустым полем «Имя пользователя», если ему разрешено открывать внешние обработки; с ТолькоПроверить база не изменится.
Многие «непонятные» ошибки проведения приходят из доработок: проверка ставит Отказ и молчит, обращается к реквизиту, которого нет у части документов из источника подписки, или перехватывает исключение и работает дальше. Шаблон обработчика подписки ПередЗаписью, который отказывает правильно:
// Общий модуль КонтрольОтгрузкиСобытия, флаг «Сервер» (имена условные).
// Обработчик подписки ПередЗаписью, источник - несколько видов документов
// отгрузки. Как доработка должна отказывать в проведении: до записи движений,
// с понятным текстом у нужного поля, через Отказ, без «глухих» Попытка.
Процедура ПроверитьОтгрузкуПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Загрузка при обмене: данные приходят как есть, проверки не выполняют
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Черновик записываем без проверок, контролируем только проведение
Если РежимЗаписи <> РежимЗаписиДокумента.Проведение Тогда
Возврат;
КонецЕсли;
// Реквизит есть не у всех документов источника: без этой проверки
// проведение «чужого» документа упадёт с «Поле объекта не обнаружено (Склад)»
МетаданныеДокумента = Источник.Метаданные();
Если МетаданныеДокумента.Реквизиты.Найти("Склад") <> Неопределено
И Не ЗначениеЗаполнено(Источник.Склад) Тогда
СообщитьОбОтказе("Не указан склад отгрузки.", Источник, "Склад", Отказ);
КонецЕсли;
ТабличнаяЧасть = МетаданныеДокумента.ТабличныеЧасти.Найти("Товары");
Если ТабличнаяЧасть = Неопределено
Или ТабличнаяЧасть.Реквизиты.Найти("Количество") = Неопределено Тогда
Возврат;
КонецЕсли;
Для Каждого СтрокаТоваров Из Источник.Товары Цикл
Если СтрокаТоваров.Количество <= 0 Тогда
// Индекс строки в пути к полю считается с нуля; XMLСтрока - без пробелов
// между разрядами, которые СтрШаблон вставил бы в число больше 999
ПутьКПолю = "Товары[" + XMLСтрока(СтрокаТоваров.НомерСтроки - 1) + "].Количество";
СообщитьОбОтказе(СтрШаблон("Строка %1: количество должно быть больше нуля.",
СтрокаТоваров.НомерСтроки), Источник, ПутьКПолю, Отказ);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Сообщение привязано к полю: в форме документа оно встанет у нужного реквизита.
Процедура СообщитьОбОтказе(Текст, Источник, Поле, Отказ)
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Текст;
Сообщение.Поле = Поле;
Сообщение.УстановитьДанные(Источник);
Сообщение.Сообщить();
Отказ = Истина;
КонецПроцедуры
Почему Отказ, а не ВызватьИсключение: проведение прервётся в обоих случаях, но с Отказ сотрудник увидит понятный текст у нужного поля, а не технический стек. Проверки, которым нужны остатки после записи движений, ставят в конец ОбработкаПроведения, как в типовой. Перехватывать исключения внутри проведения и продолжать нельзя — почему, разобрано в статье про транзакции.
ВызватьИсключение в ветке Исключение превращает понятную ошибку в «В данной транзакции уже происходили ошибки!» в другом модуле.Отказ = Истина без сообщения. Пользователь видит «Не удалось провести» и ничего больше, а обработчик приходится искать по всем подпискам.Остаток считается на момент документа, а не на сегодня: поступление того же дня с более поздним временем ещё не учтено. Ещё причины — резерв под другие заказы, другая характеристика, серия или склад, непроведённое поступление.
Разные права и разные даты запрета: в БСП дату можно задать отдельному пользователю или группе. Запустите листинг 2 с именем сотрудника, а проведение — под его учётной записью.
Обработчик выставил Отказ = Истина и не написал причину либо сообщение ушло туда, где его не видно, — например, в фоновое задание: там его забирают методом ПолучитьСообщенияПользователю фонового задания. Найдите обработчик по списку участников из листинга 3.
С самой ранней. Документы перепроводят по возрастанию даты, и одно непроведённое поступление даёт «Недостаточно товара» во всех следующих отгрузках. Исправьте первую ошибку и перезапустите. Как собрать ошибки перепроведения в журнал, описано в статье про перепроведение документов.
Проверку заполнения вызывает форма, а Записать(РежимЗаписиДокумента.Проведение) из кода её не делает. В своих обработках вызывайте ПроверитьЗаполнение() перед записью, как в листинге 1.
Остатки, даты запрета и права обычно исправляются настройкой по шагам выше. Если падает доработка или расширение, а автора кода уже нет, отдайте разбор программисту: приложите подробный текст ошибки и отчёт обработки диагностики. Разместите задачу или выберите профильную услугу по доработке 1С: оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.