gifts2017

Вариант доработки Бухгалтерии предприятия

Опубликовал Сергей Троицкий (tsd) в раздел Программирование - Практика программирования

Достаточно часто при доработке БП возникает необходимость добавления однотипных реквизитов или табличных частей в большое количество типовых документов конфигурации.  Сразу же возникает вопрос, а что с дальнейшей поддержкой? Каких временных и человеческих ресурсов будет требовать обновление конфигурации? Можно ли каким-либо образом минимизировать изменения, вносимые в типовые документы?

Предположим, что нам необходимо организовать проведение первичных документов по дополнительному регистру бухгалтерии в соответствии с таблицей распределения, задаваемой в каждом документе. При стандартном подходе нам необходимо в каждый документ добавить табличную часть и прописать обработку записи в регистр. При ближайшем рассмотрении оказывается, что нам необходимо изменить 67 документов. Как подумаешь, что при проведении обновления придется сравнивать 67 раз возможные изменения реквизитов,  форм документов и их модулей, вся бодрость духа куда-то пропадает. Как этого избежать? Нам помогут «Советы» :)

Очень хочется при открытии документа программно добавить на форму документа кнопку по нажатию которой будет открываться таблица в которую будем заносить наше распределение. Обработку записи в регистр вынесем в процедуру общего модуля (нами добавленного!), вызывать процедуру будем по подписке на событие ОбработкаПроведения.

Дабы не добавлять ТЧ в каждый документ, организуем справочник «РаспределениеОбъектов». Создаем у этого справочника ТЧ с требуемой структурой таблицы распределения, добавляем реквизит «Документ» в котором будем хранить ссылку на документ владелец. Рисуем форму элемента, которую будем вызывать для заполнения таблицы распределения. Как же нам вызвать  эту форму?

Перед открытием любого документа происходит вызов процедуры общего модуля РаботаСДиалогами.УстановитьПодменюСоветы(ЭлементыФормы.ДействияФормы, "ИмяДокумента"); добавляем в процедуру строку вызова нашей процедуры, в которой будет прописан обработчик добавления кнопки на форму документа.

Процедура УстановитьПодменюСоветы(КоманднаяПанель, ПараметрОтбора = "ВсеСоветы") Экспорт
     ...................
    
// начало изменения атт
    
ОбъектыУправленческогоУчета.ПриОткрытииФормыУпрУчет(КоманднаяПанель
);
    
// конец изменения атт
КонецПроцедуры
// УстановитьПодменюСоветы()

Таким образом, путем добавления 1 строки, мы фактически организовали подписку на событие ПриОткрытии. Этот способ не единственный по приведенным ссылкам можно посмотреть еще несколько прекрасных вариантов

http://www.infostart.ru/projects/4288

http://infostart.ru/blogs/900

Теперь нам необходимо добавить кнопку с обработчиком вызывающим форму элемента справочника. Проще всего добавить в модуль свою процедуру, но повторюсь, очень не хочется изменять модуль формы документа. Будем пробовать пользоваться существующими процедурами.

Для правильной отработки алгоритма нам необходимы две вещи:

  • распознать нажатие именно нашей кнопки;
  • иметь ссылку на документ из которого происходит вызов.

Попробуем поработать с процедурой ДействияФормыОткрытьСоветы(Кнопка), вызывающей процедуру общего модуля ОткрытьСоветы(Кнопка).  

Нашу кнопку логичнее всего распознавать по имени, Документ будем шифровать в строку пояснения кнопки. Можно добавить небольшой бантик в виде картинки кнопки. Например если таблица распределения не введена, то картинка жирный восклицательный знак, если введена, то зеленая галочка.

Ниже приведены процедуры, в которых происходит непосредственное добавление кнопки на форму документа.

 Процедура ПриОткрытииФормыУпрУчет(КоманднаяПанель) Экспорт
     Попытка
         
ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументОбъект
;
         
ДобавитьКнопкуВводУпрОбъектаВДокумент(КоманднаяПанель, ИсточникДействия
);
     Исключение
          Попытка
              
ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументСписок
;
              
ДобавитьКолонкуВТЧСпискаДокументов(КоманднаяПанель, ИсточникДействия
);
          Исключение
          КонецПопытки;
     КонецПопытки;
КонецПроцедуры

 // добавляем кнопку вызова справочника распределения на командную панель
// кнопку добавляем только для документов являющихся регистраторами регистра "УправленческийБаланс"

Процедура ДобавитьКнопкуВводУпрОбъектаВДокумент(КоманднаяПанель, Документ
)
     Если Не
ПроверитьРегистраторРегистраБухгалтерии(Документ,"УправленческийБаланс"
) Тогда
          Возврат;
     КонецЕсли;
    
СписИсключаемыхДоков = ПолучитьСписокВидовДокументовИсключений
();
     Если Не
списИсключаемыхДоков.НайтиПоЗначению(Документ.Метаданные().Имя
) = Неопределено Тогда
          Возврат;
     КонецЕсли;

     
// в строку пояснения шифруем наш документ
    
СтрокаПояснения = "Ввести объект упр. учета для: " + Документ.Метаданные().Имя + " " + СокрЛП(Документ.Номер) + " от " + Документ.Дата
;

    
нДействие = новый Действие("ДействияФормыОткрытьСоветы"
);

    
новаяКнопка = КоманднаяПанель.Кнопки.Добавить("ВводУпрОбъекта",ТипКнопкиКоманднойпанели.Действие,"Объект упр.учета",нДействие
);
    
новаяКнопка.Подсказка = "Ввести объект упр. учета"
;
    
новаяКнопка.Пояснение = СтрокаПояснения
;
    
новаяКнопка.Отображение = ОтображениеКнопкиКоманднойПанели.НадписьКартинка
;

    
УстановитьКартинкуКнопкиВводУпрОбъекта(Документ,новаяКнопка
);
КонецПроцедуры

 

При нажатии на кнопку происходит вызов процедуры общего модуля РаботаСДиалогами ОткрытьСоветы

 

 Процедура ОткрытьСоветы(Кнопка) Экспорт
     Если
Кнопка.Имя = "ВводУпрОбъекта" Тогда
// изменение атт
         
ОбъектыУправленческогоУчета.ОткрытьФормуВыбораОбъектаУпрУчета(Кнопка
);
     Иначе 
// типовой код
         
Форма = Обработки.Советы.ПолучитьФорму
();
         
Форма.ПараметрОтбора = Сред(Кнопка.Имя, 7
);
         
Форма.Открыть
();
     КонецЕсли;
КонецПроцедуры
// ОткрытьСоветы()

 

В нашей процедуре открываем форму элемента справочника распределения

 Функция ПолучитьЭлементРаспределенияОбъектовУпрУчета(Документ)
    
Запрос = Новый Запрос
;
    
Запрос.Текст
=
    
"ВЫБРАТЬ
     |      РаспределениеОбъектовУправленческогоУчета.Ссылка
     |ИЗ
     |      Справочник.РаспределениеОбъектовУправленческогоУчета КАК РаспределениеОбъектовУправленческогоУчета
     |ГДЕ
     |      РаспределениеОбъектовУправленческогоУчета.Документ = &Документ"
;
    
Запрос.УстановитьПараметр("Документ",Документ.Ссылка
);

    
Результат = Запрос.Выполнить
();

     Если
Результат.Пустой
() Тогда
          
Элемент = Справочники.РаспределениеОбъектовУправленческогоУчета.ПустаяСсылка
();
     Иначе
          
Выборка = Результат.Выбрать
();
          
Выборка.Следующий
();
          
Элемент = Выборка.Ссылка
;
     КонецЕсли;
     Возврат
Элемент
;
КонецФункции

Процедура ОткрытьФормуВыбораОбъектаУпрУчета(Кнопка) Экспорт
    
// разбираем строку пояснения в которой зашифрован документ
    
СтрокаПояснения = Кнопка.Пояснение
;
    
СтрокаПояснения = Сред(СтрокаПояснения,31
);
    
СтрокаПояснения = СокрЛП(СтрЗаменить(СтрокаПояснения,"от ",""
));
    
СтрокаПояснения = СтрЗаменить(СтрокаПояснения," ",Символы.ПС
);

    
ВидДокумента     = СтрПолучитьСтроку(СтрокаПояснения,1
);
    
НомерДокумента = СтрПолучитьСтроку(СтрокаПояснения,2
);
    
ДатаДокумента   = СтрПолучитьСтроку(СтрокаПояснения,3
);

    
День   = Число(Лев(ДатаДокумента,2
));
    
Месяц = Число(Сред(ДатаДокумента,4,2
));
    
Год     = Число(Прав(ДатаДокумента,4
));
    
ДатаДокумента = Дата(Год,Месяц,День
);

    Если (
Дата(1,1,1) = ДатаДокумента) и (НомерДокумента = ""
) Тогда
      
Сообщить("Перед выбором объекта управленческого учета документ необходимо записать",СтатусСообщения.Внимание
);
       Возврат;
    КонецЕсли;

   
// ищем документ
   
Документ = Документы[ВидДокумента].НайтиПоНомеру(НомерДокумента,ДатаДокумента
);

   
//открываем форму справочника
   
Элемент = ПолучитьЭлементРаспределенияОбъектовУпрУчета(Документ
);

    Если
Элемент.Пустая
() Тогда
        
Элемент = Справочники.РаспределениеОбъектовУправленческогоУчета.СоздатьЭлемент
();
        
Элемент.Документ = Документ
;
    Иначе
        
Элемент = Элемент.ПолучитьОбъект
();
    КонецЕсли;

   
Форма = Элемент.ПолучитьФорму("ФормаЭлемента"
);
   
Форма.ОткрытьМодально
();

   
УстановитьКартинкуКнопкиВводУпрОбъекта(Документ,Кнопка
);
КонецПроцедуры

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

Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)

 

Добавил пример в виде мини конфы. Скачать можно отсюда

http://www.infostart.ru/profile/9211/forum/9884/ 

 

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Роман Ершов (MRAK) 03.06.09 07:43
Опять же, не раскрыта тема внешнего добавления элементов на существующую форму...
2. Сергей Троицкий (tsd) 03.06.09 07:48
не совсем понял, что я должен раскрыть. Кроме кнопки никакие элементы на форму не добавляются
3. Роман Ершов (MRAK) 03.06.09 08:00
(2) пользователю было бы удобней видеть добавленные элементы в типовой форме
4. smth 03.06.09 08:24
...Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)...

А разве не нужно в модулях изменяемых документов делать подписку на события: ОбработкаПроведения, ПриЗаписи если мы их будем обрабатывать?
5. Роман Ершов (MRAK) 03.06.09 08:27
(4) при чем здесь модули доков? подписки - это отдельные объекты конфы.
6. Сергей Троицкий (tsd) 03.06.09 08:33
(4) подписка на событие устанавливается не в модуле объекта. В метаданных есть специальные объекты Общие-->"Подписки на события". В общем модуле Вы пишете свою процедуру, указываете ее как обработчик подписки, выбираете источники действия и указываете событие возникновение которого стартует Вашу процедуру. Процедура будет вызвана в конце события. Небольшим условием является то, что Ваша процедура должна содержать определенные параметры. Первым должен идти Источник действия, далее параметры стандартного обработчика 1С. Кроме того процедура должна быть экспортной.

7. Сергей Троицкий (tsd) 03.06.09 08:42
(3) Вопрос спорный. Если реквизиты расположены на форме так, что они видны сразу после открытия, то да. Если необходимо переключать закладки, то разница небольшая. Если на первую страницу панели формы напихать большое количество реквизитов, то можно форму перегрузить.
8. Андрей Скляров (coder1cv8) 03.06.09 09:39
9. Геннадий Пиганов (Totoro) 03.06.09 10:01
Теперь дошло. А что уникальный идентификатор не стал в пояснении шифровать, так по-моему проще:
GUID = СсылкаНаОбъект.ПолучитьУникальныйИдентификатор;
СсылкаНАОбъект = Документы[ВидДокумента].ПолучитьСсылку(GUID);
10. Геннадий Пиганов (Totoro) 03.06.09 10:04
(9)+ перепутал
GUID = СсылкаНаОбъект.УникальныйИдентификатор()
11. Ulcer (KapasMordorov) 03.06.09 10:37
<QUOTE>Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)</QUOTE>
В самом начале статьи написано про проведение по дополнительному регистру бухгалтерии.
Без регистратора может быть только регистр сведений. Т.е. в 67 документах нужно редактировать набор движений.
Сферический конь в ....?

12. Алексей Константинов (alexk-is) 03.06.09 11:05
Предлагаю раскрасить примеры кода
13. Сергей Троицкий (tsd) 03.06.09 11:11
(10) да я как-то про это вообще не задумывался. Получение ссылки на док труда не вызывает и ладно, кроме того пояснение выводится в строку состояния. Наверное, все же лучше видеть некую внятную подсказку, чем непонятный набор символов :)

(11) да, конечно. В приведенном примере, ессно, добавятся изменения по движениям.
Но, статья писана про организацию ввода дополнительных реквизитов с минимальными изменениями типовых форм. Поэтому и указал, что изменения всего в 2 процедурах.
Кстати, по приведенному примеру обновление все равно получается очень легким. Мы в конец справки по нашему регистру забили требуемый состав регистраторов, при обновлении никто особо не парится, после объединения просто заново прощелкивается состав регистраторов, по времени минута уходит.
В любом случае, это гораздо быстрее чем проверять формы доков :)
14. Сергей Троицкий (tsd) 03.06.09 11:13
(12) не умею :( Подскажи, плиз, куда тыкать нужно.
15. Геннадий Пиганов (Totoro) 03.06.09 11:30
(13) Это я к тому, что дата, как и номер документа являются величинами не постоянными и за время работы в форме могут быть изменены :)
16. Геннадий Пиганов (Totoro) 03.06.09 11:32
(11) Ничто не мешает использовать механизм от WiseSnake с учетом приведенного кода ... Тогда движения не нужно будет редактировать.
17. Алексей Константинов (alexk-is) 03.06.09 11:32
18. Ulcer (KapasMordorov) 03.06.09 11:41
(16) Так и получается, что на каждую мелочь нужен механизм.
И тогда простота обновления отличается от заявленной.
19. Геннадий Пиганов (Totoro) 03.06.09 11:52
(18) Извини, но тут уже готовое решение дано. Хочешь без движений - добавляей свой связанный регистр сведений, а при вызове созданной кнопки будешь открывать форму этого регистра, а не документа по его виду (можно сделать универсальную форму как для свойств) и по ссылке устанавливать подчиненые значения. Тогда изменений действительно минимум - добавить тип обекта в регистр, поведение его форм и прописать создание и выполнение кнопки из советов (можно еще использовать процедурку обновления заголовка формы в БП, что бы проверять запись нового документа и обновления ссылки на кнопке).
20. smth 03.06.09 12:54
Каким-нибудь еще механизмом можно отловить событие нажатия созданной кнопки, кроме как через "советы"? Просто советы есть не во всех конфигурациях.
21. Сергей Троицкий (tsd) 03.06.09 13:06
(17) блин, что-то не ладно с руками в датском королевстве. Оставлю как есть, лучшее враг хорошего :)
22. Сергей Троицкий (tsd) 03.06.09 13:11
(20) по ссылкам можно посмотреть другие способы обработки событий.
В УТ, например, для установки кнопки можно использовать процедуру УстановитьКнопкуПечати(), а нажатие на кнопку отлавливать через ОбновитьФормуПодбора()
Правда последняя есть только в 46 документах, нет в документах по банку, кассе и доках ввода начальных остатков
23. smth 03.06.09 13:33
А возможно отловить событие через свойство Кнопки - "Действие"?
Пр: Меню.Кнопки.Добавить(, , , Действие).
В справке написано: "Для обработки события может быть вызвана процедура или функция модуля формы или модуля приложения, имя которой задано в конструкторе."
Для того, что б не менять код документа - модуль формы не подходит. А вот в модуле приложения почему-то не запускается процедура :-(
24. Ulcer (KapasMordorov) 03.06.09 13:33
Не буду утверждать, что в каждом документе.
Но в БП в форме документа есть меню "Действия" и подпункты а)"Редактировать номер", б)"Структура подчиненности документа", для которых есть процедуры в модуле формы, вызывающие процедуры общего модуля.
25. smth 03.06.09 13:41
(24) они не передают в общий модуль имя кнопки, по которой произошло нажатие
26. Сергей Троицкий (tsd) 03.06.09 13:41
(23) у меня не получилось вызвать процедуру, расположенную не в модуле формы.
27. Ulcer (KapasMordorov) 03.06.09 13:51
(25)
Менюшку с вопросом, какое действие выполнить.
Неудобно, ну так вопрос про неудобства не идет, минимализм, понимаешь.
28. inse0f (inse0f) 03.06.09 22:22
(1) а если раскрыта просто никто не хочет ее показывать?))
29. dvv01 (dvv01) 04.06.09 11:12
ответ в http://infostart.ru/projects/4332/ - обработка табличных частей - автоматически к нужным документам добавляется меню, таб часть меняется или генерятся новые документы. Конфигурация не меняется (может только права доступа, хотя и это можно проверить в самой обработке). Примеры отобраны из Торговли, но сути не меняет
30. Ден (lion11) 15.06.09 13:18
Хорошая штука!!!
Вот только не могу понять, как отловить признак модифицированности документа перед открытием доп.формы в процедуре ОткрытьФормуВыбораОбъектаУпрУчета, чтоб можно было сохранить этот док. В ней есть проверка на существование дока. Можно это как-нибудь сделать?
31. Сергей Троицкий (tsd) 15.06.09 19:13
(30) для чего тебе признак модифицированности?
32. Ден (lion11) 16.06.09 07:52
(31) Я хочу через таким образом добавленную кнопку вызывать форму дополнительных реквизитов, типа как в http://infostart.ru/projects/4288/ , только через Советы, так меньше изменений в типовой. А если док в основной форме изменен, то в этой форме с доп.реквизитами он уже не запишется. Вот мне надо проверить, были ли изменения в текущей открытой форме дока, и с вопросом записать, а потом редактировать свои реквизиты.
33. Сергей Троицкий (tsd) 16.06.09 10:29
34. Сергей Троицкий (tsd) 17.06.09 13:30
(32) у меня проблем никаких не возникло.
По ссылке можешь качнуть пример, там все работает.


35. Ден (lion11) 17.06.09 16:53
(34) Спасибо, посмотрел. Но не увидел вот чего: если я открываю форму документа, что-нибудь на ней меняю, например номер, потом нажимаю кнопку Доп.реквизиты, не идет проверка на модифицированность, только на существование этого документа. В твоем случае - это все-равно, т.к. у тебя доп.реквизиты отдельно от документа, а у меня реквизиты принадлежат этому документу, и если я потом в доп форме жму записать - возникает ошибка. (весь смысл - чтоб типовую форму не менять) Но все равно идею приму на вооружение и буду использовать. Еще раз спасибо.
36. Сергей Троицкий (tsd) 17.06.09 20:06
(35) я думал ты в процедуру Процедура ОткрытьФормуДопРеквизитов(Кнопка)заглянешь. Там специально вставлено
ФормаОбъекта = Объект.ПолучитьФорму();
// Сообщить("Модифицированность формы: " + ФормаОбъекта.Модифицированность);

:))
37. Ден (lion11) 18.06.09 08:21
(36) Вот ведь ... :)) Смотрел в эту строчку, но просмотрел. У меня было нечто подобное, но я сначала находил объект, а потом его форму - и не работало, а тут у тебя гораздо проще. Потом почитал хелп ПолучитьФорму() для ссылки - там все написано. А так всё получилось. Огромное спасибо, что наставил на путь истинный :)
38. Ден (lion11) 21.09.09 16:18
Возник вопрос:
У меня на некоторые документы не ловится список, а именно в строке ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументСписок;
не ловится ДокументСписок. Пробовал на РКО и ав.отчеты. (Бухгалтерия предприятия 1.6.18.2). Хотя ДокументОбъект на эти доки ловится успешно.
Есть мысли, почему?
39. Сергей Троицкий (tsd) 21.09.09 19:55
(38) ИсточникДействий должен иметь значение Форма, у формы списка РКО для командной панели ДействияФормы Источник действия установлен ВсеИсточники, поэтому и не ловит
40. Ден (lion11) 22.09.09 08:26
(39) Понятно, спасибо. Поставил Форму и получилось!
Интересно, это так задумано или просто недочет разработчиков?
41. Сергей Троицкий (tsd) 22.09.09 09:31
(40) а кто ж его знает. В типовых это свойство никакой поленой нагрузки не несет, наверное просто не заполнили
42. Артур Аюханов (artbear) 02.11.09 09:23
(0) По адресу для скачивания примера лежит файл, который не загружается ни в 8.0, ни в 8.1.14.72
Какая версия 1С нужна для загрузки примера?
43. Сергей Троицкий (tsd) 02.11.09 09:33
(42) 8.1. , судя по дате, тогда у меня стоял 12 релиз платформы. Похоже просто файл битый. Посмотрю дома, если пример сохранился, то выложу заново.
44. Владимир Владимир (vladimir_che) 26.07.10 16:01
Занимательно. Ваш пост единстенный находится поиском по сайту по слову "писька".

" .НадписьКартинка "
45. Ден (lion11) 16.12.10 15:45
Грустное примечание:
Сделал это все в редакции 1.6, все красиво. Начал переходить на редакцию 2.0 - а там засада: практически нигде нет в процедурах ПередОткрытием Советов :(
Придется сделать через функцию УстановитьДоступностьПоляВводаНомера