Перед прочтением рекомендую ознакомиться с выжимкой из описания типовых методов расчета в этой статье: //infostart.ru/1c/articles/658048/
Для отладки расчета себестоимости будет очень удобно использовать методы сравнения данных в МВТ. Поясню. Весь расчет себестоимости - это формирование и перезапись временных таблиц. Их около 50 штук. Для того чтобы понимать, какие ВТ на каком этапе формируются, и какие данные в них меняются, я написал два метода и положил их в общий модуль.
На протяжении расчета во все методы передаётся структура ПараметрыРасчета, содержащая МенеджерВременныхТаблиц. Именно в нём и меняются ВТ, формируемые в разных этапах расчета.
Функция ПолучитьОписаниеТаблицМВТ(МВТ, Параметры = Неопределено, ИмяПараметра = "") Экспорт
ТаблицыМВТ = Новый ТаблицаЗначений;
ТаблицыМВТ.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ТаблицыМВТ.Колонки.Добавить("КоличествоЗаписей", Новый ОписаниеТипов("Число"));
ТаблицыМВТ.Колонки.Добавить("ТЗ");
Для Каждого цВТ Из МВТ.Таблицы Цикл
новСтрока = ТаблицыМВТ.Добавить();
новСтрока.Имя = цВТ.ПолноеИмя;
ТЗ = цВТ.ПолучитьДанные().Выгрузить();
новСтрока.КоличествоЗаписей = ТЗ.Количество();
новСтрока.ТЗ = ТЗ;
КонецЦикла;
ТаблицыМВТ.Сортировать("Имя");
Если Параметры <> Неопределено И Не ПустаяСтрока(ИмяПараметра) Тогда
Параметры.Вставить(ИмяПараметра, ТаблицыМВТ);
КонецЕсли;
Возврат ТаблицыМВТ;
КонецФункции
Функция СравнитьОписанияВТ(Описание1, Описание2, ТолькоОтличия = Истина) Экспорт
ОтличияОписаний = Новый ТаблицаЗначений;
ОтличияОписаний.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ОтличияОписаний.Колонки.Добавить("КоличествоЗаписей1", Новый ОписаниеТипов("Число"));
ОтличияОписаний.Колонки.Добавить("КоличествоЗаписей2", Новый ОписаниеТипов("Число"));
ОтличияОписаний.Колонки.Добавить("ЕстьВОписании1", Новый ОписаниеТипов("Булево"));
ОтличияОписаний.Колонки.Добавить("ЕстьВОписании2", Новый ОписаниеТипов("Булево"));
ОтличияОписаний.Колонки.Добавить("ДанныеОтличаются", Новый ОписаниеТипов("Булево"));
ОтличияОписаний.Колонки.Добавить("ТЗ1");
ОтличияОписаний.Колонки.Добавить("ТЗ2");
Для Каждого цСтрокаОписания1 Из Описание1 Цикл
новСтрока = ОтличияОписаний.Добавить();
новСтрока.Имя = цСтрокаОписания1.Имя;
новСтрока.ТЗ1 = цСтрокаОписания1.ТЗ;
новСтрока.КоличествоЗаписей1 = цСтрокаОписания1.ТЗ.Количество();;
новСтрока.ЕстьВОписании1 = Истина;
СтрокиВ2Описании = Описание2.НайтиСтроки(Новый Структура("Имя", цСтрокаОписания1.Имя));
Если СтрокиВ2Описании.Количество() = 0 Тогда
новСтрока.ДанныеОтличаются = Истина;
Иначе
новСтрока.ЕстьВОписании2 = Истина;
новСтрока.ТЗ2 = СтрокиВ2Описании[0].ТЗ;
новСтрока.КоличествоЗаписей2 = новСтрока.ТЗ2.Количество();;
Если новСтрока.КоличествоЗаписей1 <> новСтрока.КоличествоЗаписей2 Тогда
новСтрока.ДанныеОтличаются = Истина;
Продолжить;
КонецЕсли;
Для Каждого цКолонкаТЗ1 Из новСтрока.ТЗ1.Колонки Цикл
Если новСтрока.ТЗ2.Колонки.Найти(цКолонкаТЗ1.Имя) = Неопределено Тогда
новСтрока.ДанныеОтличаются = Истина;
прервать;
КонецЕсли;
КонецЦикла;
Для Каждого цКолонкаТЗ2 Из новСтрока.ТЗ2.Колонки Цикл
Если новСтрока.ТЗ1.Колонки.Найти(цКолонкаТЗ2.Имя) = Неопределено Тогда
новСтрока.ДанныеОтличаются = Истина;
прервать;
КонецЕсли;
КонецЦикла;
Если Не новСтрока.ДанныеОтличаются Тогда
новСтрока.ДанныеОтличаются = Не ОбщегоНазначения.КоллекцииИдентичны(новСтрока.ТЗ1, новСтрока.ТЗ2);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Для Каждого цСтрокаОписания2 Из Описание2 Цикл
СтрокиВОписании = ОтличияОписаний.НайтиСтроки(Новый Структура("Имя", цСтрокаОписания2.Имя));
Если СтрокиВОписании.Количество() = 0 Тогда
новСтрока = ОтличияОписаний.Добавить();
новСтрока.Имя = цСтрокаОписания2.Имя;
новСтрока.ТЗ2 = цСтрокаОписания2.ТЗ;
новСтрока.КоличествоЗаписей2 = цСтрокаОписания2.ТЗ.Количество();;
новСтрока.ЕстьВОписании2 = Истина;
новСтрока.ДанныеОтличаются = Истина;
КонецЕсли;
КонецЦикла;
Если ТолькоОтличия Тогда
ОтличияОписаний = ОтличияОписаний.Скопировать(Новый Структура("ДанныеОтличаются", Истина));
КонецЕсли;
ОтличияОписаний.Сортировать("Имя");
Возврат ОтличияОписаний;
КонецФункции
Первый метод читает все ВТ из менеджера и возвращает таблицу значений с колонками:
- Имя (имя временной таблицы),
- КоличествоЗаписей,
- ТЗ (непосредственно данные из временной таблицы).
Кроме того, этот метод может положить сформированную таблицу с описанием ВТ в любую структуру с произвольным ключом (параметры метода: Параметры, ИмяПараметра). Таким образом мы можем на любом этапе расчета создать "слепок" содержимого менеджера ВТ и положить его, например, в структуру "ПараметрыРасчета".
Второй метод позволяет сравнивать слепки, получившиеся в результате работы первого метода. В результате сравнения возвращается таблица, содержащая поля:
- Имя (имя временной таблицы),
- КоличествоЗаписей1,
- КоличествоЗаписей2,
- ТЗ1 (непосредственно данные из таблицы первого слепка).
- ТЗ2 (непосредственно данные из таблицы второго слепка).
- ЕстьВОписании1 (признак того, что ВТ присутствует в первом слепке)
- ЕстьВОписании1 (признак того, что ВТ присутствует во втором слепке)
- ДанныеОтличаются (признак того, что Данные в таблицах с одинаковым именем отличаются - по количеству записей, или по значению полей, или по наличию таблиц)
Как этим пользоваться.
1. Запускаем расчет. Можно накидать внешнюю обработку для запуска
&НаСервере
Процедура ЗапуститьРасчетССНаСервере()
ПараметрыЗапуска = Новый Структура;
ПараметрыЗапуска.Вставить("АвтоматическоеТестирование", Ложь);
ПараметрыЗапуска.Вставить("ВыполняетсяЗакрытиеМесяца", Ложь);
ПараметрыЗапуска.Вставить("Дата", НачалоМесяца(Период));
ПараметрыЗапуска.Вставить("МассивОрганизаций", ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Организация));
ПараметрыЗапуска.Вставить("МестоВызоваРасчета", "РасчетСебестоимостиКорректировкаСтоимости.Выполнить_РасчетПартийИСебестоимости");
СхемаРасчета = РасчетСебестоимостиПрикладныеАлгоритмы.СхемаРасчетаПартий(ПараметрыЗапуска.Дата, ПараметрыЗапуска.МассивОрганизаций);
Если СхемаРасчета.Количество() = 0 Тогда
новСтрока = СхемаРасчета.Добавить();
новстрока.Дата = КонецМесяца(ПараметрыЗапуска.Дата);
новстрока.ИзмененоДокументов = 1;
новстрока.Организации = ПараметрыЗапуска.МассивОрганизаций;
КонецЕсли;
ПараметрыЗапуска.Вставить("СхемаРасчета", СхемаРасчета);
РасчетСебестоимости.РассчитатьВсе(ПараметрыЗапуска);
КонецПроцедуры
Обработка во вложении, там она ещё перепроводит проблемный документ перед расчетом.
2. Тормозим отладку перед интересующим нас методом.
3. В табло пишем:
НашОбщийМодуль.ПолучитьОписаниеТаблицМВТ(ПараметрыРасчета.МенеджерВременныхТаблиц, ПараметрыРасчета, "ТаблицыПередВыполнениемЭтапа")
4. После того как выражение вычислилось, в структуре ПараметрыЗапуска появились данные с ключом "ТаблицыПередВыполнениемЭтапа", комментим (или удаляем из табло) выражение из пункта №3, чтобы данные не перезаписались при следующих шагах
5. Выполняем интересующий нас этап и кладём его данные в структуру с новым ключом. Для этого опять пишем выражение в табло:
НашОбщийМодуль.ПолучитьОписаниеТаблицМВТ(ПараметрыРасчета.МенеджерВременныхТаблиц, ПараметрыРасчета, "ТаблицыПослеВыполненияЭтапа")
6. Сравниваем эти описания, выполняя в табло код:
НашОбщийМодуль.СравнитьОписанияВТ(ПараметрыРасчета.ТаблицыПередВыполнениемЭтапа, ПараметрыРасчета.ТаблицыПослеВыполненияЭтапа)
В результате имеем Таблицу, содержащую отличия. Открыть её можно прямо из табло, нажав F2.
Также можно вместо этапов 5,6 просто идти по коду, вычисляя в табло выражение:
НашОбщийМодуль.СравнитьОписанияВТ(ПараметрыРасчета.ТаблицыПередВыполнениемЭтапа, НашОбщийМодуль.ПолучитьОписаниеТаблицМВТ(ПараметрыРасчета.МенеджерВременныхТаблиц))
Таким образом можно на любом этапе понять, какие ВТ сформировались или изменились.