BADI – Технология внедрения бизнес расширений / дополнений в код стандартных транзакций, данная техника доступна в любых модулях системы, фактически эта технология вышла для замены техники Customerexits, используя объектно-ориентированный подход к реализации расширений системы. Технология BADI призвана решить основную проблему использования точки расширения несколькими пользователями с изоляцией реализаций. Если проанализировать код системы и посмотреть места добавления вызовов BADI, то можно заменить, что вызовы добавлены до или после вызова Customerexits, т.е. функции вида CALL CUSTOMER-FUNCTION. Следовательно, в большинстве случаев можно использовать Customerexits или соответствующий ему BADI. Кстати, в таком случае в классе такого BADI перечень доступных для реализации методов, совпадает по количеству с перечнем функций в рамках компонента расширения Customerexits-а.
На данном этапе существуют два варианта реализации технологии BADI, это так называемы старые и новые BADI расширения. Различие между ними, это способ реализации класса расширения. В старых BADI, как я понимаю, реализация была сделана следующим образом, в программе в точке расширения реализовывался вызов соответствующего метода класса. Пользователю, фактически предлагалось, переопределять метод класса и таким образом выстраивалась цепочка независимых реализаций. Такая методика позволяла разнести разные реализации в свои расширения, однако проблемы в одной из наследуемых реализации могли поломать работу всех пользовательских расширений. Поэтому, через некоторое время компания перешла на новый тип BADI, теперь при реализации вы пишете класс, как наследник заранее предопределенного класса, реализующего расширение. В точке вызова система проверяет наличие всех созданных и активных инстанций – наследников от базового класса расширения и вызывает соответствующие методы всех зарегистрированных классов наследников. Перечень методов, которые будут вызваться и точки вызова, заранее определены в родительском классе. Для механизма реализации новых BADI в язык системы были введены две новые служебные команды GET BADI и CALL BADI.
Примечание: По заявлениям разработчиков SAP, новая техника BADI работает быстрее предыдущего используемого механизма. Хотя это и логично, так как новый механизм использует новые команды языка, а не вызов класса который определяет наличие расширения. Однако среднестатистический пользователь вряд ли заметит какое либо ускорение при вызовах новой или старой реализации.На первый взгляд, для пользователя особо ничего не изменяется при реализации старых или новых BADI. Однако, на самом деле отличия существенные. Новая техника расширений решила проблему хранения глобальных переменных в рамках класса реализации, что было довольно проблематично реализовать используя механизмы наследования методов. Классы реализации полностью стали независимыми и соответственно разработчики получили раздельные объекты, которые можно независимо и параллельно обрабатывать. Именно новая технология BADI, предоставляет полную изоляцию каждой инстанции, не понимание этих различий, приводит к не правильному использованию новых BADI. Например, при переходе от старого типа реализации к новому набор методов остался старый, а вот параметры методов существенно изменились, что привело к полной дезориентации части разработчиков, особенно индусских. Простой пример, в системе существует BADI: MB_MIGO_BADI – Поля пользователя на экране MIGO. В старой реализации метода, если правильно помню (к сожалению старой системы, у меня уже нет), CHECK_ITEM вам передавалась позиция документа, которую вы могли проверить на ошибки и вернуть результат проверки в параметр ET_BAPIRET2. В новой реализации в данный метод передается только значение переменной I_LINE_ID – Unique Identification of Document Line, т.е. номер позиции которую надо проверить, но данных самой позиции вам не передается. Это привело к тому, что на куче индусских форумов и части русскоязычных, скопированных из индусских, реализуется механизм сохранения вводимых позиций через IMPORT TO MEMORY в методе IF_EX_MB_MIGO_BADI~LINE_MODIFY, чтобы потом в методе проверки сделать EXPORT FROM MENORY и далее проверить значения. Я так понимаю, все реализующие этот механизм, считают себя профессионалами, а вот разработчиков компании SAP полными идиотами, которые даже нормально не понимают, что забыли передать в метод проверки сам объект проверки – позицию документа. Они, видите ли, передали какую-то непонятную переменную I_LINE_ID, которая содержит просто число, причем это число даже не является порядковым номером позиции документа. В общем, совсем не понятно как теперь работать и поэтому люди пишут какие-то кривые обходные методики для получения доступа к позициям документа внутри BADI, но при этом не просто пишут, они еще и рекомендуют их как единственно верное решение. Лично я, когда впервые столкнулся с новым BADI, и почитал предложенные механизмы, решил что это я, что-то не понимаю, но вряд ли разработчики SAP, могли так ошибиться. На самом деле, достаточно было просмотреть рекомендуемую реализацию шаблона BADI, чтобы понять, что действительно заблуждаюсь я, и действительно, в методе проверки CHECK_ITEM, при использовании нового механизма BADI, не нужно передавать строку документа.
Рекомендация: Если вы не понимаете механизма работы, не отталкивайтесь от предположения, что реализовавший данный механизм, был идиотом, так как в 99% вы просто не разобрались в решении, а 1% я оставляю на пограничные случаи.Создание расширения для транзакции MIGO
Пример работы с BADI, предлагаю рассмотреть на основе MB_MIGO_BADI, раз уже начал этот раздел с ее упоминания. Так как система новая то будем использовать механизм реализации нового BADI. Кстати, если вы выберете использовать старый или так называемый классический BADI, то все равно на определенном этапе реализации система скажет вам, что уже существует новая реализация для данного BADI, поэтому будет выполнена конвертация данных для нового механизма. Поэтому отсюда следует, что в системе не может существовать одновременно поддержка реализации старого и нового BADI для одного и того же объекта, как например MB_MIGO_BADI.
Создание точки расширения выполняется в транзакции SE19 – BAdI-Builder – внедрения, рисунок 1: badi-01.png. Транзакция работает или в режиме создания или в режиме изменения расширения. Если честно не очень распространенный вариант первого экрана транзакции. Для создания точки расширения требуется ввести имя существующей в системе точки расширения, в данном случае это MB_MIGO_BADI. Выбираем режим создания расширения.
Появится диалоговый экран с запросом создаваемой точки расширения, который будет реализовывать наше расширение. Так как основное имя MB_MIGO_BADI, то имя создаваемой точки пусть будет ZZ_MB_MIGO_BADI, имя может быть любое подходящее под соглашения по наименованию пользовательских объектов, рисунок 2: badi-02.png.
Для группировки нескольких точек расширений, которые реализуют один бизнес-процесс, можно создать групповое имя, которое будет объединять создаваемые расширения, для упрощения управления всеми реализациями. Если это просто локальная реализация, то можно не создавать групповое имя. После подтверждения создания появляется запрос на ввод имени реализации, указания класса реализации и выбора определения BADI, рисунок 3: badi-03.png, это все организовано таким образом, так как точка расширения может включать в себя несколько различных классов, фактически составляющих реализацию точки расширения. В данном случае точка расширения совпадает по имени с классом реализации, при этом класс реализации для точки только один.
После заполнения всех полей подтверждаем ввод. Система предложит нам вариант создания реализации (фактически наследуемого класса). Так как в данном случае у нас есть пример реализации и мы создаем расширение данного типа в первый раз, то лучшим выходом будет создание реализации на основе копирования примера класса. В противном случае, если вы знаете, как создавать расширение, то выбираете создание пустого класса, так как при создании копирования примера класса, создаваемый новый класс будет реализовывать все методы класса шаблона, хотя вам вполне может и не требуется реализация всех методов, рисунок 4: bapi-04.png.
Таким образом, мы получаем реализующий расширение класс с перечнем все доступных методов, которые уже изначально содержат пример правильного кода, который позволит вам написать свою реализацию по аналогии с примером. Сохраняем созданный класс и теперь можно перейти к просмотру/редактированию созданного класса расширения, рисунок 5: badi-05.png. После сохранения расширения его нужно активировать. Если расширение активно, то результат его работы можно увидеть в транзакции MIGO.
аботать с точкой расширения можно или используя и дальше транзакцию SE19 или же можно работать уже с реализующим классом используя транзакцию SE24 / SE80.
Сейчас транзакция MIGO не содержит закладки пользователя, рисунок 6: bapi-07.png, так как класс еще не активирован, но если выполнить активацию, то при просмотре документов будет доступна закладка с полями пользователя.
Так как, класс был создан на основе шаблона, то количество объектов подлежащих активации будет большим. Вы должны просто выделить все позиции и провести активацию всех объектов, рисунок 7: badi-06.png.
После активации данных в транзакции MIGO появятся закладки полей пользователя, рисунок 8: badi-08.png.
Если закладка не появилась или же при выполнении стандартной транзакции, которую вы расширили вы не попадаете в текст реализации расширения, то убедитесь что внедрение активировано и оно вызывается. Для этого в транзакции SE19 перейдите на закладку расширенные элементы внедрения и просмотрите статус расширения. Курсор должен стоять на имени BADI-внедрения, а не на реализующем классе, рисунок 9: badi-09.png.