1. Получение объекта по идентификатору.
Синхронизация справочников и документов с сайтом я предпочитаю выполнять по уникальным идентификаторам. Поэтому часто необходимо получать ссылку по идентификатору. Написал для этого универсальную функцию.
// Возвращает ссылку на найденный справочник или документ или Неопределено, если объекта нет.
// Параметры
// ИД - строковое представления уникального идентификатора
// Тип - наименование вида справочника или документа. Благо их наименования не пересекаются.
Функция ПолучитьСсылкуПоИД(ИД, Тип = Неопределено)
Если ИД = "" и Тип <> Неопределено Тогда
// Тип известен, элемент явно пустой, значит нужно вернуть пустую ссылку
спр = Метаданные.Справочники.Найти(Тип);
Если спр <> Неопределено Тогда
Возврат Справочники[Тип].ПустаяСсылка();
КонецЕсли;
док = Метаданные.Документы.Найти(Тип);
Если док <> Неопределено Тогда
Возврат Документы[Тип].ПустаяСсылка();
КонецЕсли;
Возврат Неопределено
КонецЕсли;
Попытка
УИД = Новый УникальныйИдентификатор(ИД);
Исключение
Возврат Неопределено
КонецПопытки;
// Если тип известен, то ищем только в одной таблице
Если Тип <> Неопределено Тогда
спр = Метаданные.Справочники.Найти(Тип);
Если спр <> Неопределено Тогда
Ссылка = Справочники[Тип].ПолучитьСсылку(УИД);
Если Не Ссылка.Пустая() и Ссылка.ПолучитьОбъект() <> Неопределено Тогда
Возврат Ссылка
КонецЕсли;
Возврат Неопределено
КонецЕсли;
док = Метаданные.Документы.Найти(Тип);
Если док <> Неопределено Тогда
Ссылка = Документы[Тип].ПолучитьСсылку(УИД);
Если Не Ссылка.Пустая() и Ссылка.ПолучитьОбъект() <> Неопределено Тогда
Возврат Ссылка
КонецЕсли;
КонецЕсли;
Возврат Неопределено
КонецЕсли;
// Если тип неизвестен, то перебираем все справочники и документы.
// Это долго. Поэтому тип очень хочется получить.
Для Каждого спр из Метаданные.Справочники Цикл
Ссылка = Справочники[спр.Имя].ПолучитьСсылку(УИД);
Если Ссылка.ПолучитьОбъект() <> Неопределено Тогда
Возврат Ссылка
КонецЕсли;
КонецЦикла;
Для Каждого док из Метаданные.Документы Цикл
Ссылка = Документы[док.Имя].ПолучитьСсылку(УИД);
Если Ссылка.ПолучитьОбъект() <> Неопределено Тогда
Возврат Ссылка
КонецЕсли;
КонецЦикла;
Возврат Неопределено
КонецФункции
2. Разрешение пользователям редактировать отдельные реквизиты документа без перепроведения или просто одни реквизиты разрешать, а другие запрещать.
Иногда необходимо разрешить редактирование некоторых реквизитов документа без перепроведения. Например: Комментарий, АдресКонтрагента, КонтактноеЛицо. Ещё бывает необходимым разрешить изменение отдельных реквизитов в закрытых документах. Например, поставить отметку о состоянии доставки и написать комментарий.
В модуле менеджера документа пишем функцию, которая определяет массив допустимых к редактированию реквизитов
// Возвращает массив имён реквизитов, разрешённых для изменнения без перепроведения.
// Если получен параметр типа Массив, то имена реквизитов добавляются в него
Функция ПолучитьМассивРеквизитовИзменяемыхБезПерепроведения(МассивРеквизитовДопустимыхКИзменению = Неопределено) Экспорт
Если Не ТипЗнч(МассивРеквизитовДопустимыхКИзменению) = Тип("Массив") Тогда
МассивРеквизитовДопустимыхКИзменению = Новый Массив;
КонецЕсли;
//Типовые реквизиты
МассивРеквизитовДопустимыхКИзменению.Добавить("Грузополучатель");
МассивРеквизитовДопустимыхКИзменению.Добавить("ДоверенностьНомер");
МассивРеквизитовДопустимыхКИзменению.Добавить("ДоверенностьДата");
МассивРеквизитовДопустимыхКИзменению.Добавить("ДоверенностьНомер");
МассивРеквизитовДопустимыхКИзменению.Добавить("ДоверенностьВыдана");
МассивРеквизитовДопустимыхКИзменению.Добавить("ДоверенностьЧерезКого");
МассивРеквизитовДопустимыхКИзменению.Добавить("Комментарий");
МассивРеквизитовДопустимыхКИзменению.Добавить("АдресДоставки");
//Добавленные реквизиты
Возврат МассивРеквизитовДопустимыхКИзменению;
КонецФункции
В модуле ОбщегоНазначения пишем функции общие для всех документов.
// сравниваем реквизиты документа из базы данных с записываемым объектом
// имена изменённых реквизитов запихываем в массив
Функция ПолучитьСписокИзменённыхРеквизитов(ДокОбъект) Экспорт
СписокИзменённыхРеквизитов = Новый Массив;
Ссылка = ДокОбъект.Ссылка;
мдОбъекта = ДокОбъект.Метаданные();
// сравниваем стандартные реквизиты
Для Каждого Реквизит из мдОбъекта.СтандартныеРеквизиты Цикл
Если ДокОбъект[Реквизит.Имя] <> Ссылка[Реквизит.Имя] Тогда
СписокИзменённыхРеквизитов.Добавить(Реквизит.Имя);
КонецЕсли;
КонецЦикла;
// сравниваем реквизиты шапки
Для Каждого Реквизит из мдОбъекта.Реквизиты Цикл
Если ДокОбъект[Реквизит.Имя] <> Ссылка[Реквизит.Имя] Тогда
СписокИзменённыхРеквизитов.Добавить(Реквизит.Имя);
КонецЕсли;
КонецЦикла;
// сравниваем табличные части
Для Каждого тч из мдОбъекта.ТабличныеЧасти Цикл
Если ДокОбъект[тч.Имя].Количество() = Ссылка[тч.Имя].Количество() Тогда // Не добавляли и не убирали строки в тч
Для Каждого строкаОбъекта Из ДокОбъект[тч.Имя] Цикл
СтрокаСсылки = Ссылка[тч.Имя].Получить(строкаОбъекта.НомерСтроки - 1);
Для Каждого Реквизит из тч.Реквизиты Цикл
Если СтрокаСсылки[Реквизит.Имя] <> строкаОбъекта[Реквизит.Имя] Тогда
СписокИзменённыхРеквизитов.Добавить(тч.Имя + "." + Реквизит.Имя);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Иначе
СписокИзменённыхРеквизитов.Добавить(тч.Имя);
КонецЕсли;
КонецЦикла;
Возврат СписокИзменённыхРеквизитов;
КонецФункции
// Сравниваем массив изменённых реквизитов с массивом реквизитов, разрешённых к изменению
// возвращает пустую строку, если документ можно записывать или список изменённых реквизитов из-за которых документ нельзя записать
Функция МожноЗаписыватьБезПерепроведения(ДокОбъект, МассивРеквизитовДопустимыхКИзменению, СписокИзменённыхРеквизитов = Неопределено) Экспорт
стр = "";
Если СписокИзменённыхРеквизитов = Неопределено Тогда
СписокИзменённыхРеквизитов = ПолучитьСписокИзменённыхРеквизитов(ДокОбъект);
КонецЕсли;
Для Каждого зн из СписокИзменённыхРеквизитов Цикл
Если МассивРеквизитовДопустимыхКИзменению.Найти(зн) = Неопределено Тогда
стр = стр + "
|" + зн;
КонецЕсли;
КонецЦикла;
Возврат стр;
КонецФункции
В модуле документа ПредЗаписью разрешаем запись без пререпроведения в случае, если были изменены только реквизиты, не вызывающие перепроведение.
РедактированиеЗаднимЧислом = Ложь;
МассивРеквизитовДопустимыхКИзменению = Документы.РеализацияТоваровУслуг.ПолучитьМассивРеквизитовИзменяемыхБезПерепроведения();
СписокИзменённыхРеквизитов = ОбщегоНазначения.ПолучитьСписокИзменённыхРеквизитов(ЭтотОбъект);
СписокИзменённыхРеквизитовВызывающихПерепроведение = ОбщегоНазначения.МожноЗаписыватьБезПерепроведения(ЭтотОбъект, МассивРеквизитовДопустимыхКИзменению, СписокИзменённыхРеквизитов);
Если СписокИзменённыхРеквизитовВызывающихПерепроведение = "" И Проведен И СписокИзменённыхРеквизитов.Количество() > 0 Тогда
РежимЗаписи = РежимЗаписиДокумента.Запись;
ИначеЕсли НЕ РедактированиеЗаднимЧислом и Дата < НачалоДня(ТекущаяДата()) И Не РольДоступна("ПравоАдминистрирования") Тогда
Сообщить("Недостаточно прав для проведения реализации " + Номер + " " + Строка(Дата) +
" задним числом. Изменены реквизиты: " + СписокИзменённыхРеквизитовВызывающихПерепроведение);
Отказ = Истина;
КонецЕсли;
В этой заметке не рассмотрена установка флага ТолькоПросмотр для реквизитов формы, которые нельзя редактить. Это делается сосем несложно.
Не знаю, может быть подобное решение уже есть в БСП. Не смотрел.