INFOSTART EVENT 2018 EDUCATION

Второй тур голосования за доклады.
Окончание 5 сентября.

Денисов Александр | Аналитик производительности БД | ГК Софтпоинт

«Неочевидные проблемы производительности: важность системного подхода при анализе»

• Распределенные взаимоблокировки: в чем опасность, как диагностировать и что делать дальше? «Распределенные блокировки», «синхронизация транзакций», «распределенные системы» — обычно это словосочетания, характерные для крупных систем, где сотни пользователей подключаются к геораспределенным репликам, а аналитики ищут вдохновения в измерениях олап-кубов. В секторе Small &Medium Business другие проблемы. Но даже если у вас все пользователи работают с одной-единственной клиент-серверной базой, вы все равно можете столкнуться с распределенными взаимоблокировками. Хуже того, из-за сложности диагностики программисты и администраторы могут не видеть, насколько серьезна ситуация. Мы разберем механику возникновения таких взаимоблокировок, способы диагностики и исправления ситуации. • «Железом» не прикрыть неоптимальный код. Когда аппаратное расширение уже не помогает. «Железом» не прикрыть неоптимальный код. Когда аппаратное расширение уже не помогает. Многие организации считают, что в случае острой необходимости они всегда могут «откупиться» от плохого кода вложившись в более мощную «железку» — дорого, зато быстро. Но из любого правила есть исключения. Мы разберем ситуацию, когда еще до закупки нового оборудования стало понятно, что это никак не ускорит систему.

Допиливаем форму выбора серий номенклатуры для отображения остатков

Программирование - Практика программирования

82
В этой статье я хочу рассмотреть задачу, которая довольно часто возникает у начинающих (и не только) разработчиков, адаптирующих типовые конфигурации (УТ, КА, УПП) на предприятиях торговли. Речь пойдет про отображение остатков в форме выбора серий номенклатуры при подборе в документы. Это актуально в тех случаях, когда не ведется партионный учет по сериям, либо когда документы вводятся неоперативно и нет возможности воспользоваться волшебной кнопкой "Заполнить и провести". На первый взгляд задача банальна, но я хочу показать некоторые "грабли", на которые часто наступают новички  в процессе ее реализации, а также сопоставлю алгоритмы решения на платформе 8.1 и 8.2.

Не вполне серьезная статья о вполне реальной, но часто неверно решаемой задаче. (Новичкам рекомендуется).

Итак приступим: в качестве подопытной возьмем типовую конфигурацию УТ ред. 10.3. Предполагается, что конфигурация работает на платформе 8.2 и снята с поддержки (включена возможность изменения).

 

Первый шаг, который нам необходимо будет выполнить, чтобы воспользоваться преимуществами, предоставляемыми новой платформой - это включение флажка "Использовать управляемые формы в обычном приложении". Делается это через палитру свойств конфигурации.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Ну вот, теперь можем приниматься за доработку формы списка...хотя стоп (!), возникает резонный вопрос: а зачем мы тогда ставили эту самую «галку» ? Согласен, мы не будем дорабатывать старую и толстую форму (смайл), а вместо этого создадим новую «тонкую» да к тому же еще и управляемую (хитрый смайл). Но прежде  я мысленно вернусь на несколько лет в прошлое и представлю, как бы все это выглядело имей мы дело со старушкой 8.1 Smile

Собственно, делов-то! Берем форму, добавляем на нее колонку Остаток, ну а получение и вывод на экран конечно же делаем в обработчике ПриВыводеСтроки()табличного поля. Примерно так:

Часто сталкиваюсь с таким кодом. В принципе он рабочий, но методически неверный. Во-первых неверно само размещение запроса на получение остатков в процедуре ПриВыводеСтроки(). Ведь в этом случае при выводе каждой строки будет идти обращение к базе данных и работать все это хозяйство будет неэффективно, в чем мы сможем убедиться, запустив базу в файловом режиме на слабеньком офисном ПК 2005 г.в. (кои встречаются достаточно часто). При большом количестве строк в списке - слайд-шоу гарантировано Smile. На эти грабли наступают многие новички не дошедшие пока в списке обработчиков до события ПриПолученииДанных(), а ведь оно как раз для этих целей и предназначено. Так ладно, с этим понятно, переделаем. Но ведь и  остатки мы получаем не верно: во первых общие по всем складам, а во-вторых на текущую дату. А на практике как правило складов используется несколько, да и документы могут проводится «задним числом». В этом случае ситуация усложняется. Придется каким-то образом передавать в открываемую форму данные по складу и дате остатков. В этом нам поможет обработчик поля ввода СерииНоменклатуры  НачалоВыбора(). Перво-наперво отрубаем СтандартнуюОбработку, присвоив ей значение Ложь. Дальше возможны варианты:

1)  ФормаВыбораСерий = Справочники.СерииНоменклатуры.ПолучитьФормуВыбора(,ЭтаФорма);

     ФормаВыбораСерий.ОткрытьМодально();

Вторым параметром здесь задается владелец формы, в качестве которого мы передаем саму форму документа, и тем самым переопределяем владельца  по-умолчанию, коим является непосредственно элемент поля выбора. Нам это естественно не подходит, ведь через него не получить данные  из «шапки» документа. А вот после переопределения - пожалуйста. Можно будет «докопаться» через владельца ко всем значениям его реквизитов. В принципе рабочий вариант, но как-то корявенько...

2) Более правильным представляется вариант с созданием реквизита (или экспортной переменной)  «СтруктураПараметров» (тип Структура) в форме выбора серий, и дальнейшей передачей значений в эту переменную в обработчике  НачалоВыбора(). В этом случае процедура примет вид:

Так, но это еще не все. Если теперь запустить программу в пользовательском режиме и попробовать выбрать серию, мы наступим на очередные «грабли». Когда мы отключили стандартную обработку, у нас потерялась связь серии с ее владельцем номенклатурой, поэтому сперва будет открываться форма выбора номенклатуры, а потом уже подчиненного справочника серий, что конечно же очень антигуманно по отношению к пользователям. Исправить ситуацию нам поможет такое замечательное свойство формы  (замечу только в толстом клиенте, в тонком все выглядит несколько иначе, об этом далее) как ПараметрВыборПоВладельцу, сюда нужно передать ссылку на номенклатуру владельца. Запускаем 1С:Предприятие, открываем документ реализации, нажимаем на педальку выбора серии и вуаля - очередные грабли!

Так, разбираемся...и натыкаемся еще на одно интересное свойство формы ПараметрОтборПоВладельцу. Эврика! Вот она где собака зарыта. Присваиваем ему значение нашей номенклатуры и теперь действительно все работает как надо. Конечно не все нюансы еще учтены. Например мы передаем в качестве параметра «ДатаОстатков» дату документа, но у нас на временной оси в пределах одной секунды может находится множество документов, поэтому правильнее было бы передавать МоментВремени документа, который можно получить используя одноименный метод. Вот как это должно выглядеть:

СтруктураПараметров.Вставить("ДатаОстатков",  МоментВремени());

Но и это еще не все! Laughing  Форма открывается с  отбором по владельцу, остатки показываются, но теперь перестала позиционироваться текущая строка, т.е. при открытии списка она все время находится на первой.

Для решения проблемы нужно в обработчике ПриОткрытии() теперь уже формы выбора серий присваивать свойству  ПараметрТекущаяСтрока значение нашей серии. Вот теперь после стольких мытарств все работает более и менее корректно.

 


 

В общем-то вся эта демагогия была присуща старой версии платформы, и мы сейчас посмотрим как это же самое делается в платформе 8.2 в управляемой форме (помните про галку? Cool ).

Но спешу предупредить, подводных камней тут тоже предостаточно и при отсутствии понимания как это должно быть, запросто можно дровишек подналомать.

Итак приступим. Создаем новую форму выбора, тип указываем Управляемая, на следующей вкладке выбираем отображаемые реквизиты, жмякаем ОК - форма готова. А куда нам теперь сваять колонку с остатками? Куда ее добавлять? В элементы (это те, что слева) или в реквизиты (это те что справа)? Я так отвечу: никуда не нужно ничего добавлять, чуть позже она сама волшебным образом появиться на форме.

Попробуем для начала просто открыть форму и убедится, что штатно все работает. Открываем и ...упс, что за облом??? Открылась наша старая форма. В чем тут дело? А все дело в том, что основной режим у нашей конфигурации - Обычное приложение, а форма у нас установилась на закладке Дополнительные. Это значит, что она будет открываться только при запуске в режиме управляемого приложения. А как сделать, чтобы во всех режимах открывалась управляемая форма? Для этого нужно убрать из основных обычную форму выбора и установить управляемую.

 Рестартим 1С и убеждаемся, что теперь все работатет.

ОК, сделали. Но где теперь искать событие «ПриПолученииДанных», в котором мы будем получать наши остатки? Спешу вас обрадовать, в платфторме 8.2 все делается намного проще, а все благодаря новому замечательному объекту «ДинамическийСписок» и  он-то  у нас является основным реквизитом формы. А это значит, что мы имеем полное на то право воспользоваться одной из его фишек, а именно указанием произвольного запроса. Для этого в свойствах реквизита Список (открывается через палитру свойств) ставим одноименную галку.

Теперь нажимаем на гиперссылку Открыть и видим....минуточку, где-то я это уже видел! Ах да, это та самая СКД, которая в 8.1 использовалась для построения отчетов. А вот в 8.2 на ней построены практически все списки справочников, документов и т.д. Подробно описывать свойства динамического списка я не буду, т.к. это уже выходит за пределы нашего повествования. Для нас сейчас имеет значение лишь возможность указания произвольного запроса, чем мы собственно и займемся!

Итак, у нас открылось вот такое окошко.

 

Нажимаем кнопку конструктор и конструируем наш запрос . Все поля  что были оставляем и добавляем левое соединение к ВТ таблице регистра ТоварыНаСкладахОстатки. Вот так может выглядеть текст запроса.

Сохраняем запрос и закрываем форму редактирования динамического списка. Так, что-то на форме пока не наблюдается никаких изменений, колонки как не было, так и нет. А вот и не правда Wink Она появилась в качестве реквизитов самого списка и теперь нам всего-навсего осталось перетащить ее в поле элементов списка. Вот что должно получиться в результате:

Ну вот, список готов, запрос ждет своего исполнения и все бы хорошо, но теперь не понятно, откуда платформа будет получать значения параметров в ВТ остатков? Видимо должен быть какой-то интерфейс для их передачи в запрос динамического списка. И он действительно есть, а выглядит это очень похоже на установку параметров стандартного запроса:

Список.Параметры.УстановитьЗначениеПараметра(«ИмяПараметра», ЗначениеПараметра);

Ну а дальше скорее всего остается также как и было на 8.1. Создаем структуру, затем передаем ее в реквизит (или параметр?...а может экспортную переменную?), все...алес, приплыли. Эх была ни была, сделаю как в 8.1 (здесь я специально утрирую, чтобы показать реальную ситутацию, а она к сожалению такова, что до сих пор многие работают методом тыка, не особо заботясь о корректности выбранного решения, реботает?...ну и ладно! ). Так бррр..., о чем это я? Ах да, создаем реквизит СтруктураПараметров и передаем ее также из обработчика НачалоВыбора() из документа.

Итак как передавать параметры решили, но как их получать в форме выбора серий? Точнее не как, а где именно? Первое, что приходит в голову - в процедуре ПриОткрытии(). Но это опять же неправильное решение. И вот почему. В платформе 8.2 управляемая форма существует одновременно на сервере и на клиенте, находясь при этом в разных контекстах. Обращение к базе данных возможно только из серверного контекста. Поэтому форма сперва создается на сервере, «приезжает» на клиента и только потом уже в клиентском контексте срабатывает обработчик ПриОткрытии(), который в нашем случае снова будет обращаться к серверу за данными. Таким образом правильно получать и устанавливать параметры запроса в процедуре ПриСозданииНаСервере().

Так, хорошо, переделали. Но у нас возникает другая ошибка. Программа стала ругаться как на прокаженных на свойства формы ПараметрВыборПоВладельцу и ПараметрОтборПоВладельцу. А все дело в том, что в управляемой форме нет больше таких свойств, зато появилось свойство Параметры. Вот через него то и стоило изначально передавать наши данные, а не городить новый реквизит.

И кстати, помимо всего прочего через данное свойство можно и нужно передавать и отбор в динамический список используя следующую конструкцию:

Как видим, тут же мы и устанавливаем параметр ТекущаяСтрока, чтобы правильно происходило позиционирование в списке. И открытие формы теперь происходит совсем по другому - с использованием процедуры ОткрытьФорму() (модально - частный случай), где вторым параметром мы и передаем нашу структуру.

Ну вот наконец-то все готово. Запускаем, пробуем...ура работает! Но не спешите радоваться, не все нюансы мы с вами учли: во первых мы не совсем корректно построили сам запрос. У нас жестко прописаны параметры Номенклатура и Склад, и допустим при открытии из формы документа мы нормально передадим эти параметры и запрос отработает корректно. Но что будет, если пользователь просто откроет форму выбора? Правильно - платформа выдаст ошибку, что значения параметров не установлены. Поэтому включаем смекалку и дорабатываем процедуру ПриСозданииНаСервере() и текст самого запроса. В конечном итого получаем следующие листинги:

И вот так выглядит конечный текст запроса:

Вот так вроде бы совсем простенькая задачка имеет столько подводных камней. Надеюсь эта информация кому-нибудь окажется полезной и позволит избежать встреч с граблями и плясок с бубном  в своих будущих нетленках Smile

 

82

См. также

Комментарии
Сортировка: Древо
1. mtv:) 996 25.09.11 08:36 Сейчас в теме
Статья, безусловно, полезная.
Но очень неудобно то, что код вставлен картинками, а не текстом. Невозможно перенести код простым копированием. Приходится набивать вручную… :( . Это портит общее впечатление от публикации.
Хотя все равно плюс.
Alex_will; +1 Ответить
2. practik1c 402 29.09.11 00:41 Сейчас в теме
Собственно сделал картинками потому что форматирование кода жутко неудобное да и раскраска не та :)
Но плюсы тоже есть, когда не копипастишь, а набираешь сам - усваяемость сильно лучше! ;)
3. starkv 15.10.11 15:49 Сейчас в теме
Может я что-то и не то сделал, но кажется есть ошибочка, не происходит выбор серии
из-за (Стандартная обработка = ложь)
Я сделал так:

ВыбраннаяСерия = ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров);

Если ТипЗнч(ВыбраннаяСерия) = Тип("СправочникСсылка.Серииноменклатуры")Тогда
ТекущиеДанные.СерияНоменклатуры = ВыбраннаяСерия;
КонецЕсли;
ПодводныйТ; zhurba; +2 Ответить
4. Sintson 350 19.11.11 22:01 Сейчас в теме
мАлАдец, тильки как с извечным вопросом обновления совладать, но это, как говориться ничего личного, больше к 1С вопрос, а так, тема здравая, я так же делал.
5. Dwiss 217 22.12.11 17:54 Сейчас в теме
Помоему здесь ошибочка
ДатаОстатков = <<?>>мТекущяДата(); (Проверка: Толстый клиент (обычное приложение))
ТекущаяДата() работать не будет нужно использовать
ТекущаяУниверсальнаяДата()
Синтаксических ошибок не обнаружено!
6. Hans 95 08.01.12 17:25 Сейчас в теме
Желательно бы то же самое только для табличной части документа под управляемые формы.
7. nav1971 25 11.01.12 19:21 Сейчас в теме
а куда делась статья? виднго только описание!
9. babylon_5 55 15.01.12 14:12 Сейчас в теме
(7) Открой не в IE, а в другом браузере.
8. smilejka 29 13.01.12 09:36 Сейчас в теме
Как раз сегодня планировал заниматься такой задачей. Только мне необходимо реализовать в форме подбора номенклатуры.
Статья интересная +
10. Sergeant82 01.07.12 16:27 Сейчас в теме
Огромное спасибо за публикацию! Очень выручила. Но у меня была не ТЧ, а просто Поле выбора на форме, и заработало только после добавления ", Элемент" в строке:
ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров, Элемент)
11. roma03v1 22.08.12 20:29 Сейчас в теме
Спасибо большое очень помогло, так как пока плохо программирую, очень сильно сэкономил мне время.
12. Astrakhan_man 29.10.12 12:36 Сейчас в теме
Можно вопрос, как Вы передаете дополнительные параметры (склад) в форму выбора? но я на обычных формах.
13. Astrakhan_man 29.10.12 23:36 Сейчас в теме
я создаю реквизит формы "СтруктураПараметров" с типов Произвольный (не понял как создать с типом структура), передаю в него данные
(ВыбраннаяСерия = ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров);)
, но в процедуре в "СправочникСписокПриПолученииДанных" пишет "Поле объекта не обнаружено (Склад)" где у меня ошибка.
14. Astrakhan_man 30.10.12 18:31 Сейчас в теме
переделал на управляемые формы, и при открытие пишет такую ошибку "по причине:
Ошибка получения данных
по причине:
Ошибка создания набора данных "НаборДанныхДинамическогоСписка"
по причине:
Ошибка при исполнении запроса набора данных
по причине:
{(16, 5)}: Не задано значение параметра "Дата"
<<?>>&Дата,
"

в параметрах формы(у списка) я её задал. из формы передаю.
15. katavyjob 03.07.14 14:03 Сейчас в теме
Жаль нет итоговых картинок работы данного механизма в самой программе((
16. lambert@inbox.ru 7 21.10.17 17:20 Сейчас в теме
17. user973244 23.05.18 22:30 Сейчас в теме
Да очень огромное спасибо, немного здвинула меня с места ваше решение
Оставьте свое сообщение