Никак не могу пройти один уровень в manufactoria. Грызу, как Рональдо мяч.
среда, 30 июня 2010 г.
Я вернулся!
И вот, после небольшого перерыва я снова с вами!
Поделюсь вкратце тем, что было. Во-первых я до-сих пор под впечатлением от AgileBaseCamp. Один из самых прекрасных докладчиков (из тех, на которых я попал, разумеется) это Александр Орлов, рулевой проекта Happy-PM и вообще мегамоск.
Вот он, в оранжевой футболке:
На доклад Тимофея Евграшина я не пошел специально, потому что предполагал попасть на его замечательный мастер-класс и перекинувшись парой слов "в кулуарах" утвердился в своем решении. Забегая вперед хочу сказать, что этот мастер-класс стал логическим завершением AgileBaseCamp.
Уже есть фотоотчет с мастер-класса, вот некоторые фото:
Мой шеф включается в работу:
Играем в спринт и планирование. Звучат страшные слова velocity и capacity:
Тим получил кружку QAClub:
И общее фото:
И еще одно фото, которого нет в альбоме. Оказалось, что мы возвращаемся с Тимофеем одним поездом.
Вокзал:
Подводя промежуточный итог могу сказать: мы многое поняли за этот день. Теперь знания нужно воплощать в жизнь, наступать на свои грабли и набивать свои шишки. Но мы не боимся сложностей, у нас есть стремление и план на ближайшее будущее. А заначит - все у нас получится.
Поделюсь вкратце тем, что было. Во-первых я до-сих пор под впечатлением от AgileBaseCamp. Один из самых прекрасных докладчиков (из тех, на которых я попал, разумеется) это Александр Орлов, рулевой проекта Happy-PM и вообще мегамоск.
Вот он, в оранжевой футболке:
На доклад Тимофея Евграшина я не пошел специально, потому что предполагал попасть на его замечательный мастер-класс и перекинувшись парой слов "в кулуарах" утвердился в своем решении. Забегая вперед хочу сказать, что этот мастер-класс стал логическим завершением AgileBaseCamp.
Уже есть фотоотчет с мастер-класса, вот некоторые фото:
Мой шеф включается в работу:
Играем в спринт и планирование. Звучат страшные слова velocity и capacity:
Тим получил кружку QAClub:
И общее фото:
И еще одно фото, которого нет в альбоме. Оказалось, что мы возвращаемся с Тимофеем одним поездом.
Вокзал:
Подводя промежуточный итог могу сказать: мы многое поняли за этот день. Теперь знания нужно воплощать в жизнь, наступать на свои грабли и набивать свои шишки. Но мы не боимся сложностей, у нас есть стремление и план на ближайшее будущее. А заначит - все у нас получится.
пятница, 4 июня 2010 г.
Горы и магометы
Поскольку намерение сменить место работы, с целью получения опыта по работе в команде работающей по Scrum, было признано не оптимальным, Scrum сам придет к нам в организацию.
Руководство воспринимает инициативу благосклонно, подготовка ведется, надеюсь все получится.
P.S.: В любом случае, даже если мы придем к magile это будет существенное упорядочивание процесса.
Руководство воспринимает инициативу благосклонно, подготовка ведется, надеюсь все получится.
P.S.: В любом случае, даже если мы придем к magile это будет существенное упорядочивание процесса.
среда, 2 июня 2010 г.
Серия статей "jQuery для начинающих"
Когда-то я писал пост о динамическом списке на jQuery и в процессе написания активно пользовался материалами из серии статей "jQuery для начинающих".
Оказывается, уважаемый автор продолжает ее писать и совсем недавно вышла статья о событиях.
Очень рекомендую саму статью и всю серию.
Оказывается, уважаемый автор продолжает ее писать и совсем недавно вышла статья о событиях.
Очень рекомендую саму статью и всю серию.
вторник, 1 июня 2010 г.
вторник, 25 мая 2010 г.
Снова статические методы классов в 1С
Я совершенно напрасно переживал по поводу статических методов классов, которых мне (и не только мне) так не хватает. В версии 1С 8.2 у объектов метаданных есть "Модуль менеджера" и функции описанные в нем фактически и являются статическими методами классов. Во всяком случае их можно так использовать.
Те, кто все понял, дальше могут не читать, с остальными давайте разберемся подробнее.
Те, кто все понял, дальше могут не читать, с остальными давайте разберемся подробнее.
Я сделал небольшой пример. База с тремя справочниками: "Номенклатура", "КатегорииЦен" и "Цены". Номенклатура хранит список товаров, справочник "КатегрииЦен" - просто классификатор категорий, а справочник "Цены" подчинен номенклатуре и имеет два реквизита: "Категория" и "Цена" (Число). Таким образом в нем хранится цена для конкретного товара и конкретной категории. Достаточно стандартная ситуация. (Конечно, это можно организовать и регистром сведений или еще как-нибудь, но для примера я взял справочник. Просто так.)
Скачать базу можно тут: StaticMethods.zip
А теперь самое главное. Обработка "УстановитьЦены" выводит два списка: список товаров и, при выборе конкретного товара, в правом списке будут отображены его цены по каждой категории (с возможностью редактировать).
Обычно для чтения цены пишут функцию вроде "ПолучитьЦену", на вход которой передается товар и категория (а может еще и валюта, единица измерения или много чего, в зависимости от ваших нужд) а на выходе у нее полученная цена. Иногда такую функцию пишут и для записи цены.
Если с самими функциями все понятно, то вопрос где их положить до недавнего времени оставался открытым. В 7.7 такая функция скорее всего попала бы в глобальный модуль. В результате чего глобальный модуль со временем превращался в неподъемное собрание функций. Можно было всякими ухищрениями класть функции в обработки или внешние файлы или строго соблюдать структуру и принципы комментирования глобального модуля. Все-равно это все оказывалось неудобным или мало эффективным.
В 8.1 появились общие модули (много! много! ;-) и это существенно упростило дело. Во всяком случае "помойка функций" стала расти намного медленнее и при грамотно организованной структуре общих модулей можно было быть уверенным, что другой программист найдет вашу хитрую функцию быстрее и сможет использовать ее повторно, а не писать свою. Что безусловно хорошо, так как код используется повторно. Ну, если он вообще будет что-то искать. ;-)
Однако, всегда хочется лучшего. Например, есть функции, которые относятся исключительно к какому-либо справочнику или документу, но нужны во всей конфигурации. Можно завести общий модуль по имени справочника, но не хотелось бы. Или можно было бы положить такие в модуль объекта. Но без объекта нельзя обратиться к модулю, а не всегда хочется тянуть целый объект из базы, когда достаточно ссылки (или ссылка вообще не нужна). Т.е. с одной стороны функции нужна привязка к "классу" объектов, а с другой, конкретный объект для работы функции не требуется. В ООП такая функция обязательно стала бы статическим методом класса, а в 1С 8.2 ее можно положить в "Модуль менеджера".
Обратите внимание на то, как я вызываю функцию "ПолучитьЦену" в обработке "УстановитьЦены":
Конечно, если говорить конкретно о функции "ПолучитьЦену", то вы могли бы поместить ее и в модуль менеджера справочники "Цены" или даже в "КатегорииЦен" или еще как-нибудь. Все зависит от того как вы строите архитектуру вашего приложения и какие используете соглашения при разработке. Но в любом случае возможность создать "статический метод класса" у вас есть. Что на мой взгляд - прекрасно.
Спасибо за внимание и хорошего вам кода.
Публикация на Infostart.
Скачать базу можно тут: StaticMethods.zip
А теперь самое главное. Обработка "УстановитьЦены" выводит два списка: список товаров и, при выборе конкретного товара, в правом списке будут отображены его цены по каждой категории (с возможностью редактировать).
Обычно для чтения цены пишут функцию вроде "ПолучитьЦену", на вход которой передается товар и категория (а может еще и валюта, единица измерения или много чего, в зависимости от ваших нужд) а на выходе у нее полученная цена. Иногда такую функцию пишут и для записи цены.
Если с самими функциями все понятно, то вопрос где их положить до недавнего времени оставался открытым. В 7.7 такая функция скорее всего попала бы в глобальный модуль. В результате чего глобальный модуль со временем превращался в неподъемное собрание функций. Можно было всякими ухищрениями класть функции в обработки или внешние файлы или строго соблюдать структуру и принципы комментирования глобального модуля. Все-равно это все оказывалось неудобным или мало эффективным.
В 8.1 появились общие модули (много! много! ;-) и это существенно упростило дело. Во всяком случае "помойка функций" стала расти намного медленнее и при грамотно организованной структуре общих модулей можно было быть уверенным, что другой программист найдет вашу хитрую функцию быстрее и сможет использовать ее повторно, а не писать свою. Что безусловно хорошо, так как код используется повторно. Ну, если он вообще будет что-то искать. ;-)
Однако, всегда хочется лучшего. Например, есть функции, которые относятся исключительно к какому-либо справочнику или документу, но нужны во всей конфигурации. Можно завести общий модуль по имени справочника, но не хотелось бы. Или можно было бы положить такие в модуль объекта. Но без объекта нельзя обратиться к модулю, а не всегда хочется тянуть целый объект из базы, когда достаточно ссылки (или ссылка вообще не нужна). Т.е. с одной стороны функции нужна привязка к "классу" объектов, а с другой, конкретный объект для работы функции не требуется. В ООП такая функция обязательно стала бы статическим методом класса, а в 1С 8.2 ее можно положить в "Модуль менеджера".
Обратите внимание на то, как я вызываю функцию "ПолучитьЦену" в обработке "УстановитьЦены":
Через менеджер справочника. Мне не нужен лишний общий модуль или какие-то другие ухищрения.НоваяСтрока.Цена = Справочники.Номенклатура.ПолучитьЦену(ТекущийТовар, Выборка.Ссылка);
Конечно, если говорить конкретно о функции "ПолучитьЦену", то вы могли бы поместить ее и в модуль менеджера справочники "Цены" или даже в "КатегорииЦен" или еще как-нибудь. Все зависит от того как вы строите архитектуру вашего приложения и какие используете соглашения при разработке. Но в любом случае возможность создать "статический метод класса" у вас есть. Что на мой взгляд - прекрасно.
Спасибо за внимание и хорошего вам кода.
Публикация на Infostart.
Статические методы класса
Мне ужасно нехватает возможности создавать статические методы встроенных классов метаданных в 1С.
Приходится использовать "общие модули", которые через некоторое время превратятся в помойку функций, как их не упорядочивай.
Сильнее чем мне их нехватает, наверное, только Гению1С из найденного топика на Мисте.
Приходится использовать "общие модули", которые через некоторое время превратятся в помойку функций, как их не упорядочивай.
Сильнее чем мне их нехватает, наверное, только Гению1С из найденного топика на Мисте.
воскресенье, 23 мая 2010 г.
Школа программиста
По совету Александа зарегистрировался на сайте Школа программиста (ссылка на профиль есть в разделе "Ссылки"). Решать задачи и правда очень увлекательно, и теперь когда выпадает свободная минутка я обязательно захожу туда.
понедельник, 17 мая 2010 г.
среда, 12 мая 2010 г.
Tron
Фильм Tron (1982) входит в число фильмов, которые обязательны для просмотра настоящим программистом/админом/IT-шником.
В частности, вот что пишет о нем Википедия:
Культовый фильм.
И, кстати, в декабре 2010-го должно выйти продолжение: TRON Legacy. Конечно, там будут современные спецэффекты. Но будет ли там романтика? Будет ли там Дух?
В любом случае стоит посмотреть.
В частности, вот что пишет о нем Википедия:
«Трон» — первый в истории кинематографа фильм, основные персонажи которого были полностью (вернее, почти полностью) нарисованы на компьютере. В фильме содержится около 30 минут чистой графики, где живые герои совмещены с нарисованными. Однако некоторые спецэффекты все же создавались по старинке — методом ротоскопирования и ручной раскраски каждого кадра (действие «внутри компьютера» снималось на черно-белую пленку). Кроме того, впервые в истории кинематографа в художественном фильме была продемонстрирована компьютерная анимация лица, хотя и в значительной степени упрощённая.От себя же могу добавить, что фильм, несмотря на свой наивный сюжет и "устаревшие" эффекты, на самом деле несет в себе частичку прошлого. Взгляд на (it-) жизнь тех времен. И лично я каждый раз поражаюсь насколько великими были наши (it-) предки. Какую нужно было иметь фантазию, какое стремление к новому и неизведанному, чтобы "увидеть" за черно-белыми текстовыми терминалами целый мир. (Фильм-то снимался в 1982-м, тогда даже VGA еще не изобрели, а "графика" была роскошью для пользователей). Все эти "мотоциклы", "танки", "программы"... Все это чудовищно прекрасно.
Культовый фильм.
И, кстати, в декабре 2010-го должно выйти продолжение: TRON Legacy. Конечно, там будут современные спецэффекты. Но будет ли там романтика? Будет ли там Дух?
В любом случае стоит посмотреть.
вторник, 11 мая 2010 г.
gui для git
Недавно я начал пытаться использовать git вместо моего любимого SVN. Поскольку разбираться с командной строкой мне не хотелось, я попытался найти хороший gui. Для централизованной SVN я пользуюсь хорошим клиентом TortoiseSVN, но TortoiseGIT с первого взгляда мне не понравился. Слишком не очевидный интерфейс, который, к тому же, встроен в explorer.
Попытки совладать с gui, который идет в комплекте с самим git (gitk) ни к каким к результатам не привели. Возможно, о того, что мне хотелось чтобы клиент был portable или из-за своей общей "неудобоваримости", стандартный клиент git делал все что угодно, кроме того, что мне нужно и постоянно сообщал об ошибках и неудачах, сбрасывал настройки и вел себя отвратительно.
В какой-то момент мне стало казаться, что все-таки придется курить маны по командной строке git.
Но нашел еще одно интересное gui-решение: SmartGit
Оно бесплатное для некоммерческого использования и на первый взгляд простое и понятное. Для работы требует установленного git, есть portable-версия (жужлите) и какая-то встроенная интеграция с GitHub, правда, пока не совсем понятно в чем ее смысл, если внешние репозитории все-равно нужно руками прописывать в файле .gitconfig
В целом софтина производит впечатление приятное, посмотрим что будет дальше.
Попытки совладать с gui, который идет в комплекте с самим git (gitk) ни к каким к результатам не привели. Возможно, о того, что мне хотелось чтобы клиент был portable или из-за своей общей "неудобоваримости", стандартный клиент git делал все что угодно, кроме того, что мне нужно и постоянно сообщал об ошибках и неудачах, сбрасывал настройки и вел себя отвратительно.
В какой-то момент мне стало казаться, что все-таки придется курить маны по командной строке git.
Но нашел еще одно интересное gui-решение: SmartGit
Оно бесплатное для некоммерческого использования и на первый взгляд простое и понятное. Для работы требует установленного git, есть portable-версия (жужлите) и какая-то встроенная интеграция с GitHub, правда, пока не совсем понятно в чем ее смысл, если внешние репозитории все-равно нужно руками прописывать в файле .gitconfig
В целом софтина производит впечатление приятное, посмотрим что будет дальше.
понедельник, 10 мая 2010 г.
Рутина
На всякий случай напоминаю, что я тут тренировки ради делаю небольшой проект "Деньги-дребеденьги".
Никаких полезных исходников там еще нет, но потихоньку наполняется спецификация и бэклог.
Заходите, комментируйте, предлагайте.
Никаких полезных исходников там еще нет, но потихоньку наполняется спецификация и бэклог.
Заходите, комментируйте, предлагайте.
воскресенье, 9 мая 2010 г.
Вебинар: "Что такое тестирование?"
Учебный центр Luxoft проведет вебинар на тему "Что такое тестирование?". Поскольку тестирование это важная часть разработки, то всем рекомендую.
Зарегистрироваться можно на сайте учебного центра.
Зарегистрироваться можно на сайте учебного центра.
суббота, 8 мая 2010 г.
Как менять типовую конфигурацию 1С без потери совместимости
В жизни любого 1С-программиста часто возникает необходимость доработки типовой конфигурации под нужды конкретного клиента. Иногда изменения небольшие, иногда существенные. Но в любом случае за изменениями следует наказание в виде утраты совместимости с оригинальной конфигурацией и последующей головной болью при обновлении. Думаю, что все оказывались в ситуации когда поставщик оригинальной конфигурации выпускал новую версию, а в вашей конфигурации собралось такое количество изменений, что проще было не обновляться или продать душу дьяволу или пусть это делает кто-нибудь еще, только бы не заниматься опять этим ужасным merge-ем. Что же делать? Не вносить правки? А если это необходимо и без "этой новой фичи" все "совсем развалится и непонятно как бизнес до сих пор работает без нее"?
Выход (или во всяком случае направление на него) есть. Вносить правки осторожно и обдумано. Есть множество советов по добавлению правок и множество статей о том, какие виды изменений наименее болезненны, поэтом приводить их здесь я не буду. Рассмотрим лишь один небольшой вопрос: проведение документов и собственная аналитика, которую нужно добавить.
Эта статья на Infostart
Выход (или во всяком случае направление на него) есть. Вносить правки осторожно и обдумано. Есть множество советов по добавлению правок и множество статей о том, какие виды изменений наименее болезненны, поэтом приводить их здесь я не буду. Рассмотрим лишь один небольшой вопрос: проведение документов и собственная аналитика, которую нужно добавить.
Предположим, что существует некая "типовая конфигурация". Для наглядности я сделал небольшую конфигурацию с двумя справочниками ("Товары" и "Контрагенты"), тремя документами ("Приход", "Расход", "Оплата") и тремя регистрами ("ОстаткиТоваров", "Продажи" и "Взаиморасчеты"). Принцип работы абсолютно прозрачный: фирма (наша) приходует и расходует товары, количество которых фиксируется в регистре "ОстаткиТоваров" (остаточный регистр), при "Расходе" делается движение в регистре "Продажи" на сумму расхода (регистр оборотный, измерения: контрагент, товар), а так же приход и расход двигают остаточный регистр "Взаиморасчеты" ("Приход" в минус, "Расход" в плюс), который так же двигает документ "Оплата" (в минус или в плюс выбирается перечислением "ВидыДвиженияДенег").
Еще в конфигурации есть три отчета (каждый по своему регистру) и все это объединено в подсистему "Основная" (для удобства фильтрации).
Скачать выгрузку демо-базы можно тут: begining.dt
Теперь предположим, что заказчик хочет видеть аналитику продаж по регионам. Первое, что приходит в голову - добавить справочник "Регионы". Решение верное, так как при последующем слиянии с оригинальной конфигурацией поставщика собственный справочник никак затрагиваться не будет (если в настройках не указано, что такие объекты нужно удалять, конечно). Для пущей систематизации я сделаю подсистему "Регионы" и все объекты, относящиеся к этой подсистеме, буду называть с префиксом "рг".
Что же делать дальше? Обычный путь правок предполагает, что нужно добавить реквизит "ргРегион" в документ "Расход" и сделать отчет собирающий данные из регистра и документа. Однако это не оптимальный по производительности способ и лучше было бы в регистр "Продажи" добавить еще одно измерение. Главное же неудобство состоит в том, что придется менять форму документа и вмешиваться в его модуль, изменяя функцию "ОбработкаПроведения" так, чтобы в новое измерение подставлялось значение из реквизита документа. Форма и модуль могут принести немало "радостных" минут в процессе обновления.
Какой же выход? Выход есть - подписка на события. Это прекрасная технология, появившаяся в 8-й платформе, очень нам поможет.
Итак, добавим измерение "ргРегион" типа "Справочник.ргРегионы" в регистр "Продажи". Это не сильно нам помешает при обновлении, так как обычно регистры меняются редко и даже если и меняются, то нужно просто следить за тем, чтобы наше измерение не исчезло.
Дальше есть два немного различающихся варианта реализации. Рассмотрим первый, который я назвал "Копирование документа".
Добавим в систему документ "ргРасход". Добавим в него такой же набор реквизитов, как в документе "Расход" и сделаем необходимую форму. Так же добавим в него реквизит "Регион" и разместим его на форме.
А теперь скопируем весь модуль проведения из документа "Расход" в "ргРасход". Шутка! =) Сделай мы так и все потеряло бы смысл. Нам все равно пришлось бы вносить множество изменений в "ргРасход" при обновлении. Мы пойдем другим путем.
Добавим в конфигурацию регистр сведений "ргСвязиДокументов" с двумя измерениями: "ДокументВладелец" и "Документ". Оба измерения - типа "ДокументСсылка". Пусть он у нас будет непериодический и подчиненный регистратору. В качестве регистратора укажите пока документ "ргРасход". Так же добавьте общий модуль с названием "ргРегионы" и сделайте его серверным. Пригодится.
Обработка проведения документа "ргРасход" должна делать вот что:
При отмене проведения документа "ргРасход" пусть происходят следующие действия:
Остался последний штрих - добавление нужных нам дополнительных измерений в регистр при проведении документа "Расход".
Добавим подписку на событие с именем "ргПроведение". Объект - документ "Расход", событие - "ОбработкаПроведения" и обработчик из нашего общего модуля "ргРегионы".
Функция-обработчик события должна выглядеть так:
В ней мы ищем проводимый документ в регистре "ргСвязиДокументов" и если находим (запрос не пустой и т.д.), то в движения этого документа добавляем "Регион" из документа "владельца", т.е. из того документа, который создал проводящийся сейчас документ "Расход". Так же тут добавлено небольшое условие проверки типа, которое нужно, если это событие будет вызываться для документов разных типов (мало ли куда еще понадобится вставить регион).
Давайте пройдемся еще раз с самого начала. Мы добавили некий дублирующий документ "ргРасход", при проведении которого не делается движений по оригинальным регистрам, зато создается оригинальный документ "Расход", который и делает необходимые движения. В которые мы при помощи перехвата событий добавляем свою аналитику по региону.
В конечном итоге получается, что все что мы поменяли в оригинальной конфигурации - это добавили одно измерение в регистр. Все остальное мы реализовали при помощи добавленных объектов, которые не должны вызывать сложностей при обновлении.
Для полного изящества нужно перехватывать событие "ПриЗаписи" и искать записываемый документ в регистре "ргСвязиДокументов". Если он будет найден, смотреть, не поменял ли пользователь данные в документе и отказывать в записи, если данные отличаются от документа "владельца". Это позволит избежать ошибок, которые могут появиться при ручном редактировании документов созданных автоматически.
Удалять автоматически создаваемые документы, при отмене проведения документа "владельца" не самое хорошее решение. Так как те в свою очередь могут иметь подчиненные документы или на них могут быть ссылки. При работе с реальной конфигурацией обязательно учитывайте это.
Очевидные недостатки этого способа: во-первых, все данные дублируются в двух документах, что будет влиять на размер базы, во-вторых, логика работы формы документа тоже дублируется и при обновлении формы в оригинальной конфигурации, придется вносить изменения и в вашу форму. Или не придется, если это вам не нужно. В любом случае вы должны будете внимательно проанализировать изменения оригинальной конфигурации на предмет новых реквизитов в оригинальном документе.
Недостаток дублирования логики работы формы документа так же является и существенным плюсом. Фактически вы, не вмешиваясь в оригинальную конфигурацию, можете перекроить форму документа на свой вкус, так как изменения касаются только документа созданного вами.
Посмотреть что получилось можно в файле final-1.dt
Есть другой способ, лишенный перечисленных выше недостатков. Я называю его "Документ-обертка".
Его суть заключается в том, что в документе "ргРасход" мы не дублируем документ "Расход". Документ "ргРасход" содержит в себе только реквизит "Регион" и ссылку на документ "Расход". На самой форме документа нужно сделать кнопку "Создать "Расход" по нажатию на которою создавался бы новый документ "Расход" ссылка на который хранилась бы в реквизите документа "ргРасход" и добавлялась бы запись в регистр сведений "ргСвязиДокументов". В остальном логика работы остается прежней, кроме того, что проверка на изменение документа "Расход" не нужна и в модуле проведения документа "ргРасход" не нужны никакие действия.
Итак, вкратце. У нас есть документ-обертка "ргРасход" из которого мы открываем тот документ, который должен быть дополнен нашей аналитикой. Значения наших измерений заполняется в документе-обертке, остальное заполняется в оригинальном документе, который работает как обычно: проводится, редактируется, удаляется и т.д.
Этот способ лишен недостатков способа "Копирование документа", однако у него есть другой недостаток. Пользователю придется выполнять лишнее действие по открытию документа-обертки.
Возможно, если хранить ссылки на оригинальные документы в табличной части документа-обертки и представить, будто документ-обертка это журнал, то это упростит интерфейс, но усложнит разработку. В этом направлении при желании можно поработать.
Посмотреть что получилось можно в файле final-2.dt
Конечно, все эти ухищрения будут приводить к потере производительности, но как известно за все надо платить.
Спасибо за внимание и хорошего вам кода.
Еще в конфигурации есть три отчета (каждый по своему регистру) и все это объединено в подсистему "Основная" (для удобства фильтрации).
Скачать выгрузку демо-базы можно тут: begining.dt
Теперь предположим, что заказчик хочет видеть аналитику продаж по регионам. Первое, что приходит в голову - добавить справочник "Регионы". Решение верное, так как при последующем слиянии с оригинальной конфигурацией поставщика собственный справочник никак затрагиваться не будет (если в настройках не указано, что такие объекты нужно удалять, конечно). Для пущей систематизации я сделаю подсистему "Регионы" и все объекты, относящиеся к этой подсистеме, буду называть с префиксом "рг".
Что же делать дальше? Обычный путь правок предполагает, что нужно добавить реквизит "ргРегион" в документ "Расход" и сделать отчет собирающий данные из регистра и документа. Однако это не оптимальный по производительности способ и лучше было бы в регистр "Продажи" добавить еще одно измерение. Главное же неудобство состоит в том, что придется менять форму документа и вмешиваться в его модуль, изменяя функцию "ОбработкаПроведения" так, чтобы в новое измерение подставлялось значение из реквизита документа. Форма и модуль могут принести немало "радостных" минут в процессе обновления.
Какой же выход? Выход есть - подписка на события. Это прекрасная технология, появившаяся в 8-й платформе, очень нам поможет.
Итак, добавим измерение "ргРегион" типа "Справочник.ргРегионы" в регистр "Продажи". Это не сильно нам помешает при обновлении, так как обычно регистры меняются редко и даже если и меняются, то нужно просто следить за тем, чтобы наше измерение не исчезло.
Дальше есть два немного различающихся варианта реализации. Рассмотрим первый, который я назвал "Копирование документа".
Добавим в систему документ "ргРасход". Добавим в него такой же набор реквизитов, как в документе "Расход" и сделаем необходимую форму. Так же добавим в него реквизит "Регион" и разместим его на форме.
А теперь скопируем весь модуль проведения из документа "Расход" в "ргРасход". Шутка! =) Сделай мы так и все потеряло бы смысл. Нам все равно пришлось бы вносить множество изменений в "ргРасход" при обновлении. Мы пойдем другим путем.
Добавим в конфигурацию регистр сведений "ргСвязиДокументов" с двумя измерениями: "ДокументВладелец" и "Документ". Оба измерения - типа "ДокументСсылка". Пусть он у нас будет непериодический и подчиненный регистратору. В качестве регистратора укажите пока документ "ргРасход". Так же добавьте общий модуль с названием "ргРегионы" и сделайте его серверным. Пригодится.
Обработка проведения документа "ргРасход" должна делать вот что:
- Создавать новый документ "Расход" и заполнять его так же, как и текущий "ргРасход" (кроме реквизита "Регион" и реквизита "Номер", естественно)
- Добавлять запись в регистр "ргСвязиДокументов", где в "ДокументВладелец" записывать ссылку на текущий документ "ргРасход", а в измерение "Документ" ссылку на вновь созданный документ "Расход". Важно, что тут нужно сразу записать движение в регистр, а не ждать конца процедуры обработки проведения.
- Проводить вновь созданный документ "Расход".
При отмене проведения документа "ргРасход" пусть происходят следующие действия:
- Из регистра "ргСвязиДокументов" выбираются запросом все документы "Расход", которые относятся к нашему документу "ргРасход"
- Найденные документы удаляются. (На самом деле тут должно быть не удаление, а пометка на удаление для сохранения ссылочной целостности, но не будем усложнять пример).
Остался последний штрих - добавление нужных нам дополнительных измерений в регистр при проведении документа "Расход".
Добавим подписку на событие с именем "ргПроведение". Объект - документ "Расход", событие - "ОбработкаПроведения" и обработчик из нашего общего модуля "ргРегионы".
Функция-обработчик события должна выглядеть так:
Процедура ргПроведениеОбработкаПроведения(Источник, Отказ, РежимПроведения) Экспорт ТекстЗапроса= "ВЫБРАТЬ | ргСвязиДокументов.ДокументВладелец, | ргСвязиДокументов.Документ |ИЗ | РегистрСведений.ргСвязиДокументов КАК ргСвязиДокументов |ГДЕ | ргСвязиДокументов.Документ = &ПроводимыйДокумент" ; Запрос=Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр("ПроводимыйДокумент",Источник.Ссылка); Рез=Запрос.Выполнить(); Если Рез=Неопределено Тогда Сообщить("Не выполнен запрос!"); Отказ=Истина; Возврат; КонецЕсли; Если не Рез.Пустой() Тогда ДокументВладелец=Рез.Выгрузить()[0].ДокументВладелец; Если ТипЗнч(Источник)=Тип("ДокументОбъект.Расход") Тогда Источник.Движения.Продажи[0].ргРегион=ДокументВладелец.Регион; КонецЕсли; КонецЕсли; КонецПроцедуры
В ней мы ищем проводимый документ в регистре "ргСвязиДокументов" и если находим (запрос не пустой и т.д.), то в движения этого документа добавляем "Регион" из документа "владельца", т.е. из того документа, который создал проводящийся сейчас документ "Расход". Так же тут добавлено небольшое условие проверки типа, которое нужно, если это событие будет вызываться для документов разных типов (мало ли куда еще понадобится вставить регион).
Давайте пройдемся еще раз с самого начала. Мы добавили некий дублирующий документ "ргРасход", при проведении которого не делается движений по оригинальным регистрам, зато создается оригинальный документ "Расход", который и делает необходимые движения. В которые мы при помощи перехвата событий добавляем свою аналитику по региону.
В конечном итоге получается, что все что мы поменяли в оригинальной конфигурации - это добавили одно измерение в регистр. Все остальное мы реализовали при помощи добавленных объектов, которые не должны вызывать сложностей при обновлении.
Для полного изящества нужно перехватывать событие "ПриЗаписи" и искать записываемый документ в регистре "ргСвязиДокументов". Если он будет найден, смотреть, не поменял ли пользователь данные в документе и отказывать в записи, если данные отличаются от документа "владельца". Это позволит избежать ошибок, которые могут появиться при ручном редактировании документов созданных автоматически.
Удалять автоматически создаваемые документы, при отмене проведения документа "владельца" не самое хорошее решение. Так как те в свою очередь могут иметь подчиненные документы или на них могут быть ссылки. При работе с реальной конфигурацией обязательно учитывайте это.
Очевидные недостатки этого способа: во-первых, все данные дублируются в двух документах, что будет влиять на размер базы, во-вторых, логика работы формы документа тоже дублируется и при обновлении формы в оригинальной конфигурации, придется вносить изменения и в вашу форму. Или не придется, если это вам не нужно. В любом случае вы должны будете внимательно проанализировать изменения оригинальной конфигурации на предмет новых реквизитов в оригинальном документе.
Недостаток дублирования логики работы формы документа так же является и существенным плюсом. Фактически вы, не вмешиваясь в оригинальную конфигурацию, можете перекроить форму документа на свой вкус, так как изменения касаются только документа созданного вами.
Посмотреть что получилось можно в файле final-1.dt
Есть другой способ, лишенный перечисленных выше недостатков. Я называю его "Документ-обертка".
Его суть заключается в том, что в документе "ргРасход" мы не дублируем документ "Расход". Документ "ргРасход" содержит в себе только реквизит "Регион" и ссылку на документ "Расход". На самой форме документа нужно сделать кнопку "Создать "Расход" по нажатию на которою создавался бы новый документ "Расход" ссылка на который хранилась бы в реквизите документа "ргРасход" и добавлялась бы запись в регистр сведений "ргСвязиДокументов". В остальном логика работы остается прежней, кроме того, что проверка на изменение документа "Расход" не нужна и в модуле проведения документа "ргРасход" не нужны никакие действия.
Итак, вкратце. У нас есть документ-обертка "ргРасход" из которого мы открываем тот документ, который должен быть дополнен нашей аналитикой. Значения наших измерений заполняется в документе-обертке, остальное заполняется в оригинальном документе, который работает как обычно: проводится, редактируется, удаляется и т.д.
Этот способ лишен недостатков способа "Копирование документа", однако у него есть другой недостаток. Пользователю придется выполнять лишнее действие по открытию документа-обертки.
Возможно, если хранить ссылки на оригинальные документы в табличной части документа-обертки и представить, будто документ-обертка это журнал, то это упростит интерфейс, но усложнит разработку. В этом направлении при желании можно поработать.
Посмотреть что получилось можно в файле final-2.dt
Конечно, все эти ухищрения будут приводить к потере производительности, но как известно за все надо платить.
Спасибо за внимание и хорошего вам кода.
Эта статья на Infostart
Предкомпилированные заголовки
Продолжаю изучать С++. Сегодня познакомился с предкомпилированными заголовками. Удобная штука, учитывая, что в C заголовочные файлы могут достигать существенных размеров.
Работает это так: создается заголовок (.h) к нему создается файл тела в котором только подключение заголовка после чего со специальным ключем все это компилируется. На выходе получается .pch-файл, который и является предкомпилированным заголовком. При последующих компиляциях проекта предкомпилированный заголовок повторно компилироваться не будет.
И, естественно, нужно не забывать подключать ваш заголовок (.h) в файлах проекта.
Обо всем этом, а так же о многом другом можно почитатать в MSDN.
Работает это так: создается заголовок (.h) к нему создается файл тела в котором только подключение заголовка после чего со специальным ключем все это компилируется. На выходе получается .pch-файл, который и является предкомпилированным заголовком. При последующих компиляциях проекта предкомпилированный заголовок повторно компилироваться не будет.
И, естественно, нужно не забывать подключать ваш заголовок (.h) в файлах проекта.
Обо всем этом, а так же о многом другом можно почитатать в MSDN.
пятница, 7 мая 2010 г.
DrupalCamp переносится
Из-за сложностей с местом проведения DrupalCamp переносится на 10-12 июня.
Как я уже писал - я иду.
Как я уже писал - я иду.
Подписаться на:
Сообщения (Atom)