База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как исправить функцию ПолучитьОбщиеПоказатели для корректной работы? › Ответ в теме: Как исправить функцию ПолучитьОбщиеПоказатели для корректной работы?
Ниже исправленный вариант функции. Основная замена:
|
1 |
Мета = мДокументы[0].Метаданные(); |
на получение метаданных по типу:
|
1 |
Мета = Метаданные.НайтиПоТипу(ТипЗнч(мДокументы[0])); |
Также добавлена проверка пустого массива и обработка случая, когда из формы списка передается структура с полем Ссылка.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
Функция ПолучитьОбщиеПоказатели(Знач мДокументы) Экспорт ПустойРезультат = Новый Структура( "_Вес,_Объем,_Площадь", 0, 0, 0); Если мДокументы = Неопределено Тогда Возврат ПустойРезультат; КонецЕсли; Если ТипЗнч(мДокументы) <> Тип("Массив") Тогда Возврат ПустойРезультат; КонецЕсли; Если мДокументы.Количество() = 0 Тогда Возврат ПустойРезультат; КонецЕсли; // Нормализуем массив. // В массиве должны находиться ссылки на документы. НормализованныеДокументы = Новый Массив; Для Каждого ЭлементМассива Из мДокументы Цикл Если ЭлементМассива = Неопределено Тогда Продолжить; КонецЕсли; ТипЭлемента = ТипЗнч(ЭлементМассива); // Если из формы списка пришла структура строки, // извлекаем из нее ссылку на документ. Если ТипЭлемента = Тип("Структура") Тогда СсылкаДокумента = Неопределено; Если ЭлементМассива.Свойство( "Ссылка", СсылкаДокумента) Тогда Если ЗначениеЗаполнено(СсылкаДокумента) Тогда НормализованныеДокументы.Добавить( СсылкаДокумента); КонецЕсли; КонецЕсли; Иначе // Для ссылок и объектов документов добавляем само значение. НормализованныеДокументы.Добавить( ЭлементМассива); КонецЕсли; КонецЦикла; Если НормализованныеДокументы.Количество() = 0 Тогда Возврат ПустойРезультат; КонецЕсли; мДокументы = НормализованныеДокументы; // Получаем метаданные по типу значения. // Метод Метаданные() у ссылок и объектов документов // в данном случае использовать нельзя. Мета = Метаданные.НайтиПоТипу( ТипЗнч(мДокументы[0])); Если Мета = Неопределено Тогда Возврат ПустойРезультат; КонецЕсли; // Если в массиве оказались объекты документов, // преобразуем их в ссылки. Если СтрНачинаетсяС( Строка(ТипЗнч(мДокументы[0])), "ДокументОбъект.") Тогда мРезультат = Новый Массив; Для Каждого ДокументОбъект Из мДокументы Цикл Если ДокументОбъект <> Неопределено Тогда мРезультат.Добавить( ДокументОбъект.Ссылка); КонецЕсли; КонецЦикла; мДокументы = мРезультат; Если мДокументы.Количество() = 0 Тогда Возврат ПустойРезультат; КонецЕсли; Мета = Метаданные.НайтиПоТипу( ТипЗнч(мДокументы[0])); Если Мета = Неопределено Тогда Возврат ПустойРезультат; КонецЕсли; КонецЕсли; // Определяем табличную часть. Если Мета.ТабличныеЧасти.Найти("Товары") <> Неопределено Тогда ИмяТЧ = "Товары"; ИначеЕсли Мета.ТабличныеЧасти.Найти( "ОтгружаемыеТовары") <> Неопределено Тогда ИмяТЧ = "ОтгружаемыеТовары"; Иначе Возврат ПустойРезультат; КонецЕсли; _Вес = 0; _Объем = 0; _Площадь = 0; УстановитьПривилегированныйРежим(Истина); Попытка Запрос = Новый Запрос; Запрос.УстановитьПараметр( "МассивДокументов", мДокументы); ШаблонЗапроса = "| |ВЫБРАТЬ | Таблица.*, | Таблица.Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры, | Таблица.Номенклатура.НаименованиеПолное КАК НаименованиеПолное, | Таблица.Номенклатура.Артикул КАК Артикул, | Таблица.Номенклатура.ВесЧислитель КАК ВесЧислитель, | Таблица.Номенклатура.ВесЗнаменатель КАК ВесЗнаменатель, | Таблица.Номенклатура.ВесЕдиницаИзмерения КАК ВесЕдиницаИзмерения, | Таблица.Номенклатура.ОбъемЕдиницаИзмерения КАК ОбъемЕдиницаИзмерения, | Таблица.Номенклатура.ОбъемЧислитель КАК ОбъемЧислитель, | Таблица.Номенклатура.ОбъемЗнаменатель КАК ОбъемЗнаменатель, | Таблица.Номенклатура.ПлощадьЕдиницаИзмерения КАК ПлощадьЕдиницаИзмерения, | Таблица.Номенклатура.ПлощадьЧислитель КАК ПлощадьЧислитель, | Таблица.Номенклатура.ПлощадьЗнаменатель КАК ПлощадьЗнаменатель |ИЗ | Документ.%1.%2 КАК Таблица |ГДЕ | Таблица.Ссылка В (&МассивДокументов)"; Запрос.Текст = СтрШаблон( ШаблонЗапроса, Мета.Имя, ИмяТЧ); РезультатЗапроса = Запрос.Выполнить(); Если РезультатЗапроса.Пустой() Тогда Возврат ПустойРезультат; КонецЕсли; Выборка = РезультатЗапроса.Выбрать(); Пока Выборка.Следующий() Цикл Если Не ЗначениеЗаполнено( Выборка.Номенклатура) Тогда Продолжить; КонецЕсли; Если ОбщегоНазначенияКлиентСервер .ЕстьРеквизитИлиСвойствоОбъекта( Выборка, "Отменено") И Выборка.Отменено Тогда Продолжить; КонецЕсли; Реквизиты = РеквизитыНоменклатуры( Выборка); _Вес = _Вес + ПолучитьВесВСтрокеТЧ( Выборка, Реквизиты); _Объем = _Объем + ПолучитьОбъемВСтрокеТЧ( Выборка, Реквизиты); Если Реквизиты.ПлощадьЗнаменатель <> 0 Тогда _Площадь = _Площадь + Выборка.Количество * Реквизиты.ПлощадьЧислитель / Реквизиты.ПлощадьЗнаменатель; КонецЕсли; КонецЦикла; Исключение // При необходимости здесь можно записать ошибку в журнал регистрации. Возврат ПустойРезультат; КонецПопытки; УстановитьПривилегированныйРежим(Ложь); Возврат Новый Структура( "_Вес,_Объем,_Площадь", _Вес, _Объем, _Площадь); КонецФункции |
Но в приведенном варианте есть важный нюанс: возврат из блока Попытка до выполнения строки:
|
1 |
УстановитьПривилегированныйРежим(Ложь); |
может оставить привилегированный режим включенным до завершения серверного вызова. Поэтому лучше вынести результат в переменную и отключить привилегированный режим перед единственным возвратом.
Более безопасный фрагмент завершения функции:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Результат = ПустойРезультат; УстановитьПривилегированныйРежим(Истина); Попытка // Выполнение запроса и расчет показателей Результат = Новый Структура( "_Вес,_Объем,_Площадь", _Вес, _Объем, _Площадь); Исключение Результат = ПустойРезультат; КонецПопытки; УстановитьПривилегированныйРежим(Ложь); Возврат Результат; |
## Еще одна важная правка
В вашей функции есть этот код:
|
1 |
Если ОбщегоНазначения.ЭтоРегистрСведений(Мета) Тогда |
Его лучше убрать из данной функции. Функция формирует запрос к объекту:
|
1 |
Документ.%1.%2 |
То есть она рассчитана именно на документы с табличными частями. Если передать туда регистр сведений, запрос с конструкцией Документ.ИмяРегистра.ТабличнаяЧасть будет некорректным.
Функция должна получать массив:
|
1 2 |
МассивДокументов = Новый Массив; МассивДокументов.Добавить(СсылкаНаДокумент); |
где элемент имеет тип:
|
1 |
ДокументСсылка.ИмяДокумента |
Для вашей формы списка правильное заполнение массива должно выглядеть примерно так:
|
1 2 3 4 5 6 7 8 9 10 |
МассивДокументов = Новый Массив; Для Каждого СтрокаДокумента Из Документы Цикл Если ЗначениеЗаполнено(СтрокаДокумента.Ссылка) Тогда МассивДокументов.Добавить( СтрокаДокумента.Ссылка); КонецЕсли; КонецЦикла; |
Если текущая строка формы уже является ссылкой, тогда достаточно:
|
1 |
МассивДокументов.Добавить(ТекущаяСтрока); |
После исправления перед вызовом серверной функции проверьте тип:
|
1 |
Сообщить(Строка(ТипЗнч(МассивДокументов[0]))); |
Ожидаемый результат:
|
1 |
ДокументСсылка.РеализацияТоваровУслуг |
или другой тип ссылки на документ.
Ключевая исправленная строка:
|
1 2 |
Мета = Метаданные.НайтиПоТипу( ТипЗнч(мДокументы[0])); |
А строку:
|
1 |
Мета = мДокументы[0].Метаданные(); |
нужно удалить полностью.