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