Текущее время: Чт, мар 28 2024, 12:36

Часовой пояс: UTC + 3 часа


Правила форума


ВНИМАНИЕ!

Вопросы по SAP Query и Quick View - сюда



Начать новую тему Ответить на тему  [ Сообщений: 2 ] 
Автор Сообщение
 Заголовок сообщения: Как программно присвоить триггер (Action в PPF Post Processing Framework) к фактуре?
СообщениеДобавлено: Вс, сен 05 2021, 16:18 
Младший специалист
Младший специалист

Зарегистрирован:
Сб, апр 11 2020, 21:34
Сообщения: 53
Пытаюсь сделать программу для массового присвоения триггеров (Action PPF Post Processing Framework) к фактурам.
Исходные данные:
В транзакции BEA_ACTION_DEF создан профиль (Action Profile) Z_IPMI_BILLING с триггером (Аction) Z_IPMI_BILLDOC, который надо присвоить выборке фактур.
В транзакции /BEA/IPMI11 можно присвоить триггер (Action) к выбранной из таблицы /1BEA/IPMI_BDH фактуре. Mне нужно сделать автоматическое присвоение триггера для выборки фактур, чтобы потом все выбранные фактуры с присвоенным триггером обработать в программе RSPPFPROCESS.
Ориентируюсь на два следующих руководства:
http://pavelgk.pbworks.com/f/Post+Processing+Framework+(PPF)+Guidelines+for+application+developers.pdf
http://www.sapspot.com/sap-transportation-management-trigger-ppf-post-processing-framework-action-from-stand-alone-code/
Также пытаюсь следовать логике присвоения триггера фактуре в транзакции /BEA/IPMI11 с помощью отладчика.

Выкладываю эскиз кода. На данный момент не удается присвоить триггер фактуре. Просьба профессионалов скорректировать и направить на путь истиный.

0) Используемые переменные:
Code:
data: bdh_guid      type bea_bdh_guid.
data: g_manager type ref to cl_manager_ppf.
data:lo_trigger    type ref to cl_trigger_ppf.
data: lo_appl_object  type ref to cl_bea_ppf.
data:lo_trigger    type ref to cl_trigger_ppf.
data: lv_applkey      type ppfdappkey.
data: lo_partner      type ref to cl_bea_partner_ppf,
      lo_partner_coll type ref to cl_partner_coll_ppf.
data: l_notif_found type dnot_flag.
data: lt_context     type ppftcntxts.
data:  ls_context      type ppfdctxtir.

1) Получаем instance of PPF manager:
Code:
try.
      g_manager = cl_manager_ppf=>get_instance( ).
      check g_manager is bound.
  endtry.


2) Список фактур передается во внутреннюю таблицу. На данном этапе список ограничен фактурой с id='4000100573':
Code:
select bdi~bdi_guid,  bdh~bdh_guid,  bdi~src_guid, bdh~headno_ext, bdi~src_headno,bdh~bill_date,bdh~bill_type,bdi~item_category,bdh~bill_org, bdh~parset_guid
   into table @lt_lty_bdi
   from  /1bea/ipmi_bdi as bdi

   inner join /1bea/ipmi_bdh as bdh on bdi~bdh_guid = bdh~bdh_guid
   "where bill_type  between 'ZIF1' and 'ZIF8' and  bdi~src_headno in @s_objid and bdh~headno_ext in @s_faktid "and bdh~bill_org  > 0.
   where bdh~headno_ext = '4000100573'.

loop at lt_lty_bdi into ls_lty_bdi.   "цикл через список фактур


3) Создаем persistence object lo_appl_object для выбранной фактуры:
Code:
    try.
        lo_appl_object =
          ca_bea_ppf=>agent->get_persistent( ls_lty_bdi-bdh_guid ).
      catch cx_os_object_not_found.
        lo_appl_object =
          ca_bea_ppf=>agent->create_persistent( ls_lty_bdi-bdh_guid ).
        lo_appl_object->set_bea_name('IPMI').   "is_bty-application
    endtry.


4) Создаем и заполняем объект контекста к lo_appl_object:
Code:
if l_context is initial.
      create object l_context.
    endif.

    call function 'BEA_PPF_O_GET_APPLKEY'    "Трансформация номера фактуры в корректный lv_applkey: IPMI_4000100573
      exporting
        iv_application = 'IPMI'         "  is_bty-application
        iv_headno_ext  = ls_lty_bdi-headno_ext
      importing
        ev_applkey     = lv_applkey.

    l_context->name =     'Z_IPMI_BILLING'.       " Action Profile
    l_context->appl = lo_appl_object.             "Здесь передается параметр созданного persistence object  lo_appl_object для выбранной фактуры
    l_context->applctn =  'BILLING'.              " Application Name.   
ls_context = l_context.
    append ls_context to lt_context.



5) Выборка по business partner и добавление выборки в объект контекста:
Code:
call function 'BEA_PAR_O_GET'
      exporting
        iv_parset_guid = ls_lty_bdi-parset_guid
      importing
        et_par         = lt_partner
      exceptions
        reject         = 1
        others         = 2.
    loop at lt_partner into ls_partner.
*     create a partner object
      create object lo_partner
        exporting
          ip_partner_role  = ls_partner-partner_fct
          ip_partner_no    = ls_partner-partner_no
          ip_partner_text  = ''
          ip_zav_addressno = ls_partner-addr_nr
          ip_zav_persno    = ls_partner-addr_np
          ip_zav_addr_type = ls_partner-addr_type.
*    add partner object to partner collection
      call method lo_partner_coll->add_element( lo_partner ).
    endloop.
* update partner collection to context
    loop at lt_context assigning <lf_context>.
      <lf_context>->partner = lo_partner_coll.
    endloop.


6) Создаем объект триггера (Action = Z_IPMI_BILLDOC ) на основе ранее созданного объекта контекста и instance of ppf manager
На данном этапе происходит сбой. Триггер не инизиализируется:
Code:
   if lo_trigger is initial.
      " Create trigger for PPF action
      g_manager->create_trigger(
      exporting
      ip_ttype_name = 'Z_IPMI_BILLDOC'   "iv_ttype
      io_context = l_context
      receiving
      ro_trigger = lo_trigger
      exceptions
      empty_triggertype = 1
      empty_context = 2
      others = 3 ).
      if sy-subrc <> 0.
        raise error_trigger_creation.
      endif.
    endif.

    g_manager->set_applkey(   "* Set application key for all triggers of the context
    exporting
    ip_applkey = lv_applkey
    io_context = l_context ).

commit work and wait.

  endloop.

Возможно, надо вызывать метод g_manager->add_trigger(...)
Но как тогда добавить необходимый триггер Z_IPMI_BILLDOC? В данном методе нет такого параметра.
Если кто-нибудь имеет опыт в данном вопросе, большая просьба скорректировать, подсказать.


Пометить тему как нерешенную
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Как программно присвоить триггер (Action в PPF Post Processing Framework) к фактуре?  Тема решена
СообщениеДобавлено: Вт, ноя 22 2022, 19:18 
Младший специалист
Младший специалист

Зарегистрирован:
Сб, апр 11 2020, 21:34
Сообщения: 53
Сохраню здесь. Решение с год как работает.
Обобщение: массовое присвоение Actions в CRM к фактурам с последующей oбработкой в программе RSPPFPROCESS.

*
Code:
&---------------------------------------------------------------------*
*& Report ZREP_FAKTIRA_ARCHIV
*&---------------------------------------------------------------------*
*& REPORT für die Massenzuweisung von Aktionen zur Fakturen.
*&
*&  Aktionsprofil: Z_IPMI_BILLING
*&  Aktion Z_IPMI_BILLDOC: wenn die BILL_ORG der Faktura der GP # 4 ist und das BILL_DATE der Faktura < '20210407' und die Nummer des Vertrags zur Faktura zwischen '0900000000' und '0910000000' liegt
*&  Aktion Z_IPMI_BILLDOC_KOMMI: wenn die BILL_ORG der Faktura der GP # 6007 ist und das BILL_DATE der Faktura < '20210407' und die Nummer des Vertrags zur Faktura zwischen '0910000000' und '0920000000' liegt
*&  Aktion Z_IPMI_BILLDOC_VERSCHM: wenn die BILL_ORG der Faktura der GP # 4 oder der GP # 6007 ist und das BILL_DATE der Faktura > '20210407' sowie die Nummer des Vertrags zur Faktura größer oder gleich '0920000000' ist
*&---------------------------------------------------------------------*
report zrep_faktura_archiv.

tables :/1bea/ipmi_bdh,/1bea/ipmi_bdi.

types:
  begin of lty_bdi,
    "    bdi_guid      type bea_bdi_guid,
    bdh_guid    type bea_bdh_guid,
    src_guid    type crmt_object_guid,
    headno_ext  type bea_headno_ext,
    src_headno  type bea_src_headno,
    bill_date   type bea_bill_date,
    bill_type   type bea_bill_type,
    "    item_category type bea_item_category,
    bill_org    type bea_bill_org,
    parset_guid type bea_parset_guid,
  end of lty_bdi.

constants:
      lc_act1       type string value 'IPMI_BILLDOC'.

data: lv_ppf_mode     type ppfdmode,
      gv_ttype_name   type  ppfdtt,
      lo_ppf_manager  type ref to cl_manager_ppf,
      gv_data_changed type bea_boolean,
      lv_act          type ppfdtt,
      gv_headno_alt   type  bea_headno_ext,
      lt_trigger      type ppfttrgor,
      lt_partner      type beat_par_wrk,
      ls_partner      type beas_par_wrk,
      lt_lty_bdi      type table of lty_bdi,
      ls_lty_bdi      like line of lt_lty_bdi,
      lv_erfolg       type i.

data: gt_inactiv_trigger type ppfttrgor.
data: gt_activ_trigger type ppfttrgor.
data: gs_activ_trigger type ppfdtrgor.
data: gs_inactiv_trigger type ppfdtrgor.
data ls_action type crmt_action_get.
data lt_action type crmt_action_get_tab.


select-options:
s_faktid for /1bea/ipmi_bdh-headno_ext,
s_objid for /1bea/ipmi_bdi-src_headno.

data: l_context type ref to cl_notif_context_ppf.
data: l_ez_context type ref to ppfdcntxt.
"data:  l_appl_object type ref to cl_notif_ppf.
data: g_manager type ref to cl_manager_ppf.
"data: l_notif_found type dnot_flag.
data: lt_context     type ppftcntxts.
data: ls_context      type ppfdctxtir.
data: gd_trigger         type ref to data.
"data: go_proxy       type ref to cl_okcode_ppf.
data:lo_trigger    type ref to cl_trigger_ppf.
data: lr_print_medium_ppf   type ref to  cl_sf_print_ppf.
data: lv_applkey      type ppfdappkey.
data: lo_appl_object  type ref to cl_bea_ppf.
data: lo_partner      type ref to cl_bea_partner_ppf,
      lo_partner_coll type ref to cl_partner_coll_ppf.
data: lv_status type ppfdtstat.
data: o_coll type ref to cl_trigger_coll_ppf.
"data: lref_bcs           type ref to cl_bcs.

field-symbols <lf_context> type ppfdctxtir.

initialization.

  "  s_objid[]  = value #( ( sign = 'I' option = 'BT' low = '0800000000' high = '0809999999' )
  "                        ( sign = 'I' option = 'BT' low =  '0900000000' high = '0920000000' )
  "                      ).

start-of-selection.

  data: lv_answer type c.

  lv_act = lc_act1.

  try.
      g_manager = cl_manager_ppf=>get_instance( ).
      check g_manager is bound.
  endtry.


  g_manager->locale_update = 'X'.

  data: it_result type table of zrep_forecast_line,
        lv_excl   type char4.

  select distinct
"    bdi~bdi_guid,
    bdh~bdh_guid,
    bdi~src_guid,
    bdh~headno_ext,
    bdi~src_headno,
    bdh~bill_date,
    bdh~bill_type,
"    bdi~item_category,
    bdh~bill_org,
    bdh~parset_guid
    into table @lt_lty_bdi
    from  /1bea/ipmi_bdi as bdi
    inner join /1bea/ipmi_bdh as bdh on bdi~bdh_guid = bdh~bdh_guid
    where
    bdi~item_category <> 'ZI11' and bdi~item_category <> 'ZI22' and
       "( ( bill_type  between 'ZIF1' and 'ZIF8' )  and ( src_headno between  '0800000000'  and '0899999999' ) and  bdi~src_headno in @s_objid and bdh~headno_ext in @s_faktid "and bdh~bill_org  > 0.
        bdi~src_headno in @s_objid and bdh~headno_ext in @s_faktid.

  sort   lt_lty_bdi by src_headno headno_ext.


  call function 'POPUP_TO_CONFIRM'
    exporting
      titlebar              = 'Aktionen zu den ausgewählten Fakturen zuweisen'
      text_question         = 'Wollen Sie wirklich die Aktionen zu den ausgewählten Fakturen zuweisen?'
      text_button_1         = 'Ja'
      display_cancel_button = ''
      icon_button_1         = 'ICON_OKAY'
      text_button_2         = 'Nein'
      icon_button_2         = 'ICON_CANCEL'
      default_button        = '2'
    importing
      answer                = lv_answer "Rückgabewerte: '1', '2', 'A'
    exceptions
      text_not_found        = 1
      others                = 2.

  if sy-subrc <> 0.
    message i531(0u) with 'Fehler beim Funktionsbaustein POPUP_TO_CONFIRM'.
    return.
  endif.

  if lv_answer = '2' or
     lv_answer = 'A'.
    return.
  endif.

  clear gv_headno_alt.

  loop at lt_lty_bdi into ls_lty_bdi.
    lv_erfolg = 0.

    if gv_headno_alt <> ls_lty_bdi-headno_ext.

      gv_headno_alt = ls_lty_bdi-headno_ext.

      clear: lo_appl_object.
      refresh lt_context.
      try.
          lo_appl_object =
            ca_bea_ppf=>agent->get_persistent( ls_lty_bdi-bdh_guid ).
        catch cx_os_object_not_found.
          lo_appl_object =
            ca_bea_ppf=>agent->create_persistent( ls_lty_bdi-bdh_guid ).
          lo_appl_object->set_bea_name('IPMI').   "is_bty-application
      endtry.

      clear l_context.
      clear lo_trigger.
      if l_context is initial.
        create object l_context.
      endif.

      "CREATE OBJECT lref_bcs.

      call function 'BEA_PPF_O_GET_APPLKEY'
        exporting
          iv_application = 'IPMI'         "  is_bty-application
          iv_headno_ext  = ls_lty_bdi-headno_ext
        importing
          ev_applkey     = lv_applkey.


      if ( ls_lty_bdi-src_headno < '0900000000' ).
        l_context->name =     'IPMI_BILLING'.
      else.
        l_context->name =     'Z_IPMI_BILLING'.       "l_type_notif-ppf_profil.
      endif.

      l_context->appl = lo_appl_object.
      l_context->applctn =  'BILLING'.              "l_type_notif-ppf_appl.


      o_coll = g_manager->get_triggers( l_context ).
      o_coll->reset_iterator( ).

      do.
        call method o_coll->get_next_element
          receiving
            ro_element = lo_trigger
          exceptions
            others     = 1.
        if sy-subrc ne 0.
          exit.
        endif.

        if lo_trigger is not initial.
          lv_status  = lo_trigger->get_status( ).
          if lv_status = 0.
            g_manager->delete_trigger( io_context = l_context io_trigger = lo_trigger io_force = crmkc_con_yes ).
          endif.
        endif.
      enddo.

      "      ls_context = l_context.
      "     append ls_context to lt_context.

      "      check lt_context is not initial.
*
**   create partner collection
*      create object lo_partner_coll.
*
*      call function 'BEA_PAR_O_GET'
*        exporting
*          iv_parset_guid = ls_lty_bdi-parset_guid
*        importing
*          et_par         = lt_partner
*        exceptions
*          reject         = 1
*          others         = 2.
*      loop at lt_partner into ls_partner.
**     create a partner object
*        create object lo_partner
*          exporting
*            ip_partner_role  = ls_partner-partner_fct
*            ip_partner_no    = ls_partner-partner_no
*            ip_partner_text  = ''
*            ip_zav_addressno = ls_partner-addr_nr
*            ip_zav_persno    = ls_partner-addr_np
*            ip_zav_addr_type = ls_partner-addr_type.
**    add partner object to partner collection
*        call method lo_partner_coll->add_element( lo_partner ).
*      endloop.
** update partner collection to context
*      loop at lt_context assigning <lf_context>.
*        <lf_context>->partner = lo_partner_coll.
*      endloop.
*
*      clear gv_ttype_name.
*      clear lo_trigger.
*
*      call method g_manager->get_active_triggers
*        exporting
*          it_contexts = lt_context
*        importing
*          et_triggers = gt_activ_trigger.
*
*      loop at gt_inactiv_trigger into gs_inactiv_trigger.
*        ls_action-guid = gs_inactiv_trigger->read_guid( ).
*        "                ls_action-def = gs_inactiv_trigger->get_ttype( ).
*        "                ls_action-text = cl_view_service_ppf=>get_descrp_for_dropdown( io_trigger = gs_inactiv_trigger ).
*        "lv_status  =  gs_inactiv_trigger->get_status( ).
*      endloop.
*
*      if  lines( gt_activ_trigger ) > 0.
*        g_manager->delete_all_triggers_for_object( lo_appl_object ).
*      endif.
*
*

*
      format color col_normal.

      if (  ls_lty_bdi-src_headno between '0800000000' and '0899999999') .

          gv_ttype_name = 'IPMI_BILLDOC'.

        perform create_trigger using gv_ttype_name
                                     l_context
                               changing lv_erfolg.

        if lv_erfolg = 0.
          write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name, |  |, 'ERFOLG!'.  "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
        endif.

      elseif ( ( ls_lty_bdi-src_headno between '0900000000' and '0900099999') and ls_lty_bdi-bill_org =  '0000000004' ).  "and ls_lty_bdi-bill_date <  '20210407'


          gv_ttype_name = 'Z_IPMI_BILLDOC'.
*
        perform create_trigger using gv_ttype_name
                                     l_context
                               changing lv_erfolg.

        if lv_erfolg = 0.
          write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name, |  |, 'ERFOLG!'.  "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
        endif.

      elseif ls_lty_bdi-src_headno between '0910000000' and '0910099999' and ( ls_lty_bdi-bill_org = '0000006007' or ls_lty_bdi-bill_org = '0000000004' ). "and ls_lty_bdi-bill_date <  '20210407'.

          gv_ttype_name = 'Z_IPMI_BILLDOC_KOMMI'.
*
        perform create_trigger using gv_ttype_name
                                     l_context
                               changing lv_erfolg.
        if lv_erfolg = 0.
          write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name, |  |, 'ERFOLG!'.  "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
        endif.

"     elseif ( ls_lty_bdi-src_headno between '0920000000' and  '0929999999' ).
        elseif ( ls_lty_bdi-src_headno >= '0920000000').
      "  and ( ls_lty_bdi-bill_org = '0000006007' or  ls_lty_bdi-bill_org = '0000000004' ) and ls_lty_bdi-bill_date >  '20210407'.
        gv_ttype_name = 'Z_IPMI_BILLDOC_VERSCHM'.

        perform create_trigger using gv_ttype_name
                                     l_context
                               changing lv_erfolg.

        if lv_erfolg = 0.
          write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name, |  |, 'ERFOLG!'.  "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
        endif.

*       else.
*
*          gv_ttype_name = 'Z_IPMI_BILLDOC'.
*          perform create_trigger using gv_ttype_name
*                                     l_context
*                               changing lv_erfolg.
*          if lv_erfolg = 0.
*          write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name, |  |, 'ERFOLG!'.  "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
*        endif.

      endif.

    endif.

  endloop.

end-of-selection.

  commit work and wait.

form create_trigger using lv_ttype_name type  ppfdtt
                          lo_context type ref to cl_notif_context_ppf
                    changing lv_erfolg type integer.



  data: ev_rc type i.
  data: lref_bcs           type ref to cl_bcs.
  data: lo_medium  type ref to if_medium_ppf.
  data: lo_trigger  type ref to cl_trigger_ppf.

  clear lo_trigger.


  g_manager->create_trigger(
     exporting
     ip_ttype_name =    lv_ttype_name  "iv_ttype
     io_context = lo_context
     receiving
     ro_trigger =  lo_trigger "co_trigger
     exceptions
     empty_triggertype = 1
     empty_context = 2
     others = 3 ).
  if  sy-subrc <> 0.
    format color col_negative.
    lv_erfolg = 1.
    write: / ls_lty_bdi-src_headno,| |, ls_lty_bdi-headno_ext,|   |,ls_lty_bdi-bill_type, |      |, ls_lty_bdi-bill_date, |       |,ls_lty_bdi-bill_org,  |    |, gv_ttype_name,  |  |, 'FEHLER!'. "ls_lty_bdi-bdh_guid,  ls_lty_bdi-src_guid,
    "  raise error_trigger_creation.
    clear lo_trigger.
  endif.


  if lo_trigger is not initial.
    lo_trigger->set_partindep( i_partindep = abap_true ).
  endif.

  if lr_print_medium_ppf is initial.
    create object lr_print_medium_ppf.
  endif.

  if  lo_trigger is bound.
*    create object lref_bcs.
    lo_medium = lo_trigger->get_medium( ).
    if lo_medium is bound.
      lr_print_medium_ppf ?= lo_medium.
      call method lr_print_medium_ppf->set_device( 'LOCL' ).
      call method lr_print_medium_ppf->set_copies( '001' ).


***Set the medium of PPF Action
      call method lo_trigger->set_medium
        exporting
          i_medium = lr_print_medium_ppf.
    endif.
  endif.

  g_manager->set_applkey(
  exporting
     ip_applkey = lv_applkey
     io_context = l_context ).


*  call method co_trigger->execute
*    receiving
*      rp_rc                   = ev_rc
*    exceptions
*      empty_medium_reference  = 1
*      empty_appl_reference    = 2
*      locked                  = 3
*      document_is_locked      = 4
*      inactive                = 5
*      startcondition_not_true = 6
*      others                  = 7.

  clear gt_inactiv_trigger.

  call method g_manager->get_inactive_triggers
    exporting
      it_contexts = lt_context
    importing
      et_triggers = gt_inactiv_trigger.

  if lines( gt_inactiv_trigger ) > 0.
    "   write: /   ls_lty_bdi-headno_ext.
    loop at  gt_inactiv_trigger into gs_inactiv_trigger.
      gs_inactiv_trigger->if_action_ppf~activate( exceptions failed = 1 ).
    endloop.
  endif.


endform.


Пометить тему как нерешенную
Вернуться к началу
 Профиль Отправить email  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot]


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB