среда, 25 декабря 2013 г.

Повторное использование кода в трансформации

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

Варианты:
PERFORM - не работает в классах с одной стороны, и не знает ничего о типах внутри класса с другой. Описывать допольнительно тип из класса, тоже не интересно.
ФМ - т.к. код тупой и не предполагается его где-либо использовать, некрасиво. Опять же типы.
INCLUDE - тоже вариант, но не самый безопасный.

 Предлагаемый выход - создать свой метод.

1) Объявляем свой метод внутри класса
*$*$ begin of global - insert your declaration only below this line  *-*
    METHODS
      simple
        EXPORTING
          MONITOR                  type rstr_ty_t_monitors
         CHANGING
          RESULT_PACKAGE           type _ty_t_TG_1.

*$*$ end of global - insert your declaration only before this line   *-*

2) Создаем реализацию (т.с. самая фишка - нам доступен только метод end_routine или inverse)
Но не все потеряно, мы закрываем метод end_routine просто написав ENDMETHOD.
А ниже пишем реализацию своего класса, которая будет закрываться ENDMETHOD, который нам достался от метода end_routine. 
*----------------------------------------------------------------------*
*       Method end_routine
*----------------------------------------------------------------------*
*       Calculation of result package via end routine
*       Note: Update of target fields depends on rule assignment in
*       transformation editor. Only fields that have a rule assigned,
*       are updated to the data target.
*----------------------------------------------------------------------*
*   <-> result package
*----------------------------------------------------------------------*
  METHOD end_routine.
*=== Segments ===

    FIELD-SYMBOLS:
         TYPE _ty_s_TG_1.

    DATA:
      MONITOR_REC     TYPE rstmonitor.

*$*$ begin of routine - insert your code only below this line        *-*
... "insert your code here
*--  fill table "MONITOR" with values of structure "MONITOR_REC"
*-   to make monitor entries
... "to cancel the update process
*    raise exception type CX_RSROUT_ABORT.

"Вызов нашего метода
    me->SIMPLE(
*      IMPORTING
*        MONITOR        =
      CHANGING
        RESULT_PACKAGE = RESULT_PACKAGE
    ).




  ENDMETHOD.  "закрываем метод end_routine

"реализация нашего метода
  METHOD simple.
    FIELD-SYMBOLS:
         TYPE _ty_s_TG_1.

    DATA:
      MONITOR_REC     TYPE rstmonitor.

    BREAK-POINT.

*$*$ end of routine - insert your code only before this line         *-*
  ENDMETHOD.                    "end_routine

upd. Будет работать только если нет ни одной рутины 

среда, 4 декабря 2013 г.

Инфо-источник типа без контекта

Давненько с этим не сталкивался, даже как то подзабыл.

Ситуация. По help'y нашли источник, вроде оно - активируем в RSA5
Тиражируем источник как новый- все ок. Он появился, сделали пару загрузок, данные устраивают... пытаемся найти следующие трансформации и цели.

И вот тут нас поджидает облом, т.к. в бизнес-контенте нету такого источника, ни нового, ни старого. Куб если находиться то активируется без трансформации\update rule к источнику.

Решение. Конвертируем с помощью RSDS в старый тип источника. Заходим, активируем и вот тут появляться окошко которое предлагает поднять данные из бизнес-контента. Когда старый data staging поднят, то его потом можно мигрировать в новые типы.

доп.фишка... по поводу суслика которого не видно, а он есть. Если Вы сделали пакеты к источнику, а потом его вернули к старому типу с помощью RSDS, то пакетов Вы не увидите, хотя они есть. Но пакеты созданные в старом источнике после миграции видны.

понедельник, 25 ноября 2013 г.

Замеры времени при выполнении трансформации

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

DATA:
  l_t0 type i,
  l_t1 type i,
  l_t2 type i,
  l_t3 type i,
  l_t4 type i,
  l_t5 type string,
  l_t6 type string.

 GET RUN TIME FIELD l_t0. "Get time for transformation

 GET RUN TIME FIELD l_t1. "Get time for block
"
" some code
"
 GET RUN TIME FIELD l_t2. l_t3 = ( l_t2 - l_t1 ).
 l_t4 = l_t3 / 1000000.
 monitor_rec-msgid = 'RSRMON'.
 monitor_rec-msgty = 'W'.
 monitor_rec-msgno = '000'.
 monitor_rec-msgv1 = 'start '.   "block name
 l_t5 = l_t3.
 l_t6 = l_t4.
 CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
 DESCRIBE TABLE RESULT_PACKAGE LINES l_t3.
 l_t5 = l_t3.
 l_t6 = l_t4.
 CONCATENATE ' RESULT_PACKAGE - ( ' l_t5 ' )' INTO monitor_rec-msgv3.
 monitor_rec-msgv4 = SPACE.
 append monitor_rec to MONITOR.

 И так "цать раз + в конце вычисляем общее время

l_t3 = ( l_t2 - l_t0 ).
l_t4 = l_t3 / 1000000.
monitor_rec-msgid = 'RSRMON'.
monitor_rec-msgty = 'W'.
monitor_rec-msgno = '000'.
monitor_rec-msgv1 = 'TOTAL'.
l_t5 = l_t3.
l_t6 = l_t4.
CONCATENATE l_t6 '( ' l_t5 ' )' INTO monitor_rec-msgv2.
monitor_rec-msgv3 = SPACE.
monitor_rec-msgv4 = SPACE.
append monitor_rec to MONITOR.

Виртуальный куб, дайте два

Понадобилось тут в виде эксперимента протестировать изменения логики виртуального куба. Решил сделать обработку в одном модуле, но привязать её к имени куба и соответственно сделать второй мультик но на том же ФМ. И все это хозяйство в один мультик было положено. Система падала в дамп при попытке выполнить любой отчет на этом мультике. Пришлось дублировать модуль, тогда все заработало нормально.

вторник, 17 сентября 2013 г.

Нашел хорошую транзакцию se39 - позволяет сравнить программы даже если у них разные имена. (+ по RFC)

четверг, 18 апреля 2013 г.

DTP особенность

Столкнулся с небольшой спецификой отработка DTP, хотя в принципе если подумать, то все логично. Итак в DTP существует по сути две опции (да 4, но по сути 2) - создавать Error PSA или не создавать.
И в случае если при загрузке приходят некорректные символы, получается следующая ситуация:

1. с Error PSA - загрузка падает на этапе Filter Out New Records with the Same Key.
У Вас есть возможность данные поправить руками. Но этот этап идет до трансформации, соответственно Вы не можете поставить заглушку в трансформации.


Максимум что у Вас есть, это DS, где Вы можете поставить подпрограмму конвертации.


* идея поставить промежуточный IS с трансформацией была - но не пробовал. да и схема усложняется.

2. Без Error PSA, падает уже на этапе обновления данных, т.е. после трансформации  Но тут никаких ручных корректировок, зато есть трансформация.

В общем при правильной изменяемости системы, в случае цейтнота, можно пользоваться тем или иным подходом.

понедельник, 15 апреля 2013 г.

Service Pack

Немного сервисов по пакам и зависимостям:


Нашел хороший сервис - Upgrade Dependency Analyzer  - http://service.sap.com/uda
Как пользоваться неплохо написано здесь - http://scn.sap.com/message/13965049

Поиск sp



  • http://service.sap.com/swdc/
      --> Support Packages & Patches
        --> SAP Support Package Stack
          --> SP Stack maintenance schedule
            --> Ваш продукт в табличке, например SAP EHP2 for SAP NetWeaver 7.0
Кхм, готовлюсь к upgrade исходной

RSDDSTATWHM - позвонила найти все активные источники данных
ROOSFIELD - для сравнения структур экстракторов до и после

Нашел не плохой список проверок после обновления


  • Check list for a general BW upgrade
    1)Extraction
    Creation of Infopackage
    Execution of infopackage with filters(Dynamic and static) and without filters.
    Modify an existing infopackage
    Data Extraction from LO data sources(Full, Delta, Repair Full, Init,repeat delta)
    Data Extraction from Generic data sources(Full and delta)

    2) Modelling
    Creation and Execution of DTPwith filters(Dynamic and static) and without filters.
    Modify an existing DTP.
    Check for functioning of interactive DTP Code.
    Functionalities of Semantic groups and various Update modes in DTP settings.
    Creating of Error DTPs.
    Delta Intialization in DTP
    Check for functionality of start, end, and transformation routine. ( Mainly check the syntax errors in end routine )
    Aggregation behaviour with and without start routine.
    Update behaviour of end routine.
    Over write and Additive functionality of transformation.
    Delta functionality in DSO and change log entry creation.
    Check Delta Consistency from Write Optimized DSO
    DSO data load and activation of DSO data. (Both 3.5 flow and 7.0 flow)
    Data mart loads (execution of DTP in 7.0 flow and u201Cfurther updateu201D for 3.5 flow).
    Deletion data from DSO and Cube ( Selective, request based and full)
    Delete and create index.
    Cube Compression
    Rollup of Aggregates
    Request deletion in ODS/Cube

    3) Process Chains
    Run process chains for Master(with attribute change run)
    Run process chain for transaction loads which has a full flow i.e source sytem extraction to Aggregate roll up.
    Check for Metachain execution
    Remotely calling a process chain from a source system
    Event based trigger of process chains
    Deletion of PSA and Changelog using process chains
    Deltion of contents using process chain
    Execution of ABAP pgms using process chains
    Functioning of decision making and interrupts in process chains.

    4) Front End
    Execution of report on Bex, Portal, RSRT
    Customer exit variable
    Virtual Characteristics/Key figures.
    Text variables with replacement path.
    Check for Formula variables.
    Run time Unit and/or Currency conversions.
    Hierarchy variables or Hierarchy.
    Query execution using RRMX (IN BEX)
    Creation of a work Book and refresh the work book.
    All existing functionalities of work like copy sheet,Global and local variables
    Excel version of queries.
    Broadcasting a workbook and query

    5) IP
    Create, Change , activate an Aggregation Level,Filter, Planning sequence,Planning Function
    Test the functionality of Planning Functions
    Test the reason entry Functionality

    6) Others
    Creation and Execution of APD
    Creation and execution of Open Hub
    Data Archiving in Write Optimized DSO and Standard DSO
    Run SE38 pgms

Миграция авторизации



вторник, 9 апреля 2013 г.

CO-PA: Delta update no longer possible due to realignment

Столкнулся с проблемой загрузки из CO-PA - Delta update no longer possible due to realignment.
В конечном итоге оказалось что коллеги из ERP подсобили... у них есть транзакция которая напрямую формируем изменения в учете результатов, но без формирования дельты.
Эта операция отслеживается и система информирует о том, что данные могут быть некорректны.

Подробнее тут - http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/c0e0d25d-cb7f-2e10-6abd-de25831a4efb?overridelayout=true

Но все со временем меняется и есть более "чистый" способ поставить галку ‘FLAG DIRTY - Without Consistency Check’.

SBIW

Выбрать источник, и перейти к техническим параметрам, поставить галку на флаг и сохранить.



После загрузки данных, галку можно убрать, чтобы проверка на работа.
Ну а дальше, либо Вам повезло и поле(я) которое меняли Вам не нужно,  тогда всё.
Если нужно, то все зависит от Вашей модели... full обычно :)

UPD. Full пакету пофигу на этот флаг. Init тоже нормально заходил. А вот дельта все равно сломалась... Просто коллеги в тесте подкинули ситуацию, было интересно как отработает.

четверг, 28 марта 2013 г.

Экстракция и оптимизация

Всегда поражает, что единажды написанное в примерах SAP применяется прямо и перпердикулярно.  Как пример, обработка C_T_DATA[] в расширении экстрактора.


Обычная картинка:

DATA:

  L_T_DATA type STANDARD TABLE OF mc11va0hdr.

FIELD-SYMBOLS:
  <L_S_DATA> TYPE mc11va0hdr.

L_T_DATA[] = C_T_DATA[].

LOOP AT L_T_DATA ASSIGNING <L_S_DATA>.

ENDLOOP.
C_T_DATA[] = L_T_DATA[].


При этом кроме цикла ничего нету...
Вопрос - зачем терять время и память на операции присвоения.


Да, структура C_T_DATA типа неизвестна...
Но есть же вариант проще

FIELD-SYMBOLS:
  <L_S_DATA> TYPE mc11va0hdr.

LOOP AT С_T_DATA ASSIGNING <L_S_DATA>.
ENDLOOP.

Надо знать структуру, потому что ....
Пожалуйста...
TYPES:
  LT_DATA type table of mc11va0hdr.

FIELD-SYMBOLS:
  <LT_DATA>  TYPE LT_DATA,
  <L_S_DATA> TYPE LINE OF LT_DATA.

ASSIGN C_T_DATA TO <LT_DATA>.
LOOP <LT_DATA> AT ASSIGNING <L_S_DATA>.
ENDLOOP.

Цифры:
  Было 22 сек стало 18 сек на 8000 записей
  Было 41 минут, стало 11 на 1 900 000 записях

четверг, 14 марта 2013 г.

Кнопки в Bex

Временами переставали работать кнопки в Bex. Стал разбираться... порадовал "суперкод" определения где что показывать\гасить.

Public Sub AdjustButtons()

On Error Resume Next
Dim lsheet As Worksheet
' Adjust Filter Button
If pFilterVisible Then
  For Each lsheet In ThisWorkbook.Sheets()
    If lsheet.Range("C14").Value = "Filter" Then
....
'Adjust InfoButton

If pFilterVisible Then
  For Each lsheet In ThisWorkbook.Sheets()
    If lsheet.Range("F5").Value = "Information" Then

Соответственно появление фразы Filter в ячейке C14 и Informationd F5 востанавливало работу кпопок.

Классы сообщений

Тексты в классах сообщений находяться в таблице T100. Очень удобно :)

Есть ещё таблицы

T100A Message IDs for T100
T100C Message Control by User
T100O Assignment of message to object
T100S Configurable system messages
T100SA Application Areas for Configurable Messages
T100T Table T100A text
T100U Last person to change messages
T100V Assignment of messages to tables/views
T100W Assign Messages to Workflow
T100X Error Messages: Supplements
T100ARBGB Application Area

класс R9O - сообщения похожие на Bex, но на самом деле х.з.

вторник, 5 марта 2013 г.

APPEND:

Встретил тут в коде удобный APPEND

DATA: r_typ_x TYPE RANGE OF typ_x.


APPEND:              
                'IEQ10' TO r_typ_x,  "Условие А
                'IEQ12' TO r_typ_x.  "Условие Б


append |ILE{ p_par }| to s_par[].
append |IGT{ p_par }| to k_par[].
append |IEQ00000000| to d_par[].
append |IEQ{ zcl_utils=>get_type( ) } | to lr_type.

7.4
lt_AGGA  TYPE TABLE OF abap_compname WITH EMPTY KEY. " table of  fields

  lt_AGGA  = VALUE #( ( 'Field1' ) ( 'Field2' ) ( 'Field3') ).


LOOP AT lt_AGGA ASSIGNING FIELD-SYMBOL().
              ASSIGN COMPONENT OF STRUCTURE TO .

TABLE_LINE


DATA itab TYPE RANGE OF i.
itab = VALUE #( sign = ‘I’  option = ‘BT’ ( low = 1  high = 10 )
                                          ( low = 21 high = 30 )
                                          ( low = 41 high = 50 )
                            option = ‘GE’ ( low = 61 )  ).

  lr_customer = VALUE #(
  FOR <ls_customer> IN lt_customer
  ( sign = 'I'
    option = 'EQ'
    low = )
  ).


DATA:  lr_L_Port type range of /BIC/OIZL_PORT.

    lr_L_Port = VALUE #(
      FOR <ls_t_var_range> IN i_t_var_range
        WHERE ( vnam = 'D_ZL_PORT_CEOO01' )
     ( sign   = -SIGN
       option = -OPT
       low    = -LOW
       high   = -HIGH

     ) ).

CONCATENATE LINES OF lt_sales_order INTO l_logtmp separated by ';'.

* Select fields
DATA:
    ls_view TYPE ZVTETATET,
    lo_struct TYPE REF TO cl_abap_structdescr,

    lt_fields TYPE STANDARD TABLE OF FIELDNAME.

"get list of fields
    lo_struct ?= cl_abap_typedescr=>describe_by_data( ls_view ).
    lt_fields = VALUE #(
      FOR <ls_comp> IN lo_struct->get_components( )

         ( |V~{ -name },| ) ).
...

понедельник, 4 марта 2013 г.

Тех.контект

В рамках борьбы с саботажем, активировали тех.контент. В принципе все ок, за исключение одного при первой загрузке информации по цепочкам (экстрактор 0TCT_DS21) теряли 4 часа. Переписка с SAP. Ноты. Непомогло... но при этом получили "забавный" workaround.

В таблице RSDDSTATEXTRACT по источнику храниться timestamp для выборки данных (для источника 0TCT_DS21 из таблицы RSPCPROCESSLOG). Был выяснен  интересный факт, что при загрузке данных с ограничениями в пакете, timestamp не правильно формировался. + не правильно формируется дельта при инициализации с переносом.

действия:

1. Снять ограничения с пакетов (мы не хотели грузить старые).
2. Прогрузить инициализацию без переноса
3. Прогрузить дельту - и вот тут в 1й дельте приходят все данные
4. Дальнейшие дельты идут корректно

пятница, 22 февраля 2013 г.

Активация DSO

Медитировал на тему активации DSO... точнее какой % активации DSO, и идти мне спать, или маленько посидеть, чтобы пнуть процесс дальше.

Если зайти в лог активации, то можно увидеть что основное время тратиться на записи типа :
BIBCTL_DEPEQUQGFT5PS7P03XM99IHON with ID 23311900

  Вопрос, и сколько этих ID может быть? В общем формула почти простая  

Кол-во записей ID = (Кол-во Записей которые будут вставлены) / (размер пакета активации = 20000 by default) + Random(0|1|2)  

Таким образом зная общее кол-во записей, можно посчитать сколько уже сформировалось в логе, т.е. можно посчитать % активации...  

Формула была проверена на 23 больших активациях, поэтому и появился коэффициент Random.
Удачных активаций!

Для изменения размера пакета активации DSO используется транзакция  RSODSO_SETTINGS.

среда, 30 января 2013 г.

Global query variant

Оказалось, что не все знают, что можно создавать глобальные варианты для запуска отчета.
Делается это достаточно просто, при создании варианта надо убрать галку Save as User Variant, задать тех.имя и сохранить.


Объект авторизации - S_RS_PARAM (необходим в случае глобальных вариантов)

Таблицы - RSRPARAMETRIZA (вариант и параметры) и RSRPARAMETRIZAT (тексты)

Интересные поля:

PARENTCOMPONENT - тип объекта
1 Query
2 Workbook
3 Web Application
4 Planning Sequence
5 Planning Function
6 Enterprise Report

ELTUID - тех.имя запроса
PERSONAL - локальный (X) и глобальный (SPACE) вариант
OWNER - user id создателя
CONTENT - содержание варианта в XML формате

Перенос - стандартного (по одной кнопке) способа переноса не существует. Но есть варианты.

Руками в транспорт
PgmID Obj     Object name

R3TR  TABU RSRPARAMETRIZA
R3TR  TABU RSRPARAMETRIZAT

С помощью ведения таблицы *

- SE16
- ‘RSRPARAMETRIZA’
- Нажать кнопку ‘table Contents’ (or F7)
- Провалится в контент (‘F8′)
- Выделить записи для траспортировки
- В меню выбрать ‘table Entry’ -> ‘Transport Entries’
- Выбрать запрос на перенос

* но много на формах сообщений, что способ не работает, закрыт пункт ‘Transport Entries’








понедельник, 28 января 2013 г.

Float

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

Почитал ещё курс BC402, порадовала фраза...
Внимание: Для вычислений в арифметике с плавающей запятой используются операции с плавающей запятой соответствующих процессоров. Поскольку алгоритмы выполняются над двоичными числами, могут возникать погрешности. Степень и эффект таких погрешностей не поддаются оценке.

Теперь, на примере...

DATA:

l_value1 TYPE p DECIMALS 5 value '1.755',
l_value2 TYPE f value '1.755',

l_result1 TYPE p DECIMALS 1,
l_result2 TYPE p DECIMALS 2,
l_result3 TYPE p DECIMALS 3,
l_result4 TYPE p DECIMALS 4.

l_result1 = l_value1. write / l_result1.
l_result2 = l_value1. write / l_result2.
l_result3 = l_value1. write / l_result3.
l_result4 = l_value1. write / l_result4.

l_result1 = l_value2. write / l_result1.
l_result2 = l_value2. write / l_result2.
l_result3 = l_value2. write / l_result3.
l_result4 = l_value2. write / l_result4.

Результат:
[b]l_value1 TYPE p DECIMALS 5 value '1.755'[/b]

0.0 1.8
0.00 1.76
0.000 1.755
0.0000 1.7550

[b]l_value2 TYPE f value '1.755'[/b]
0.0 1.8
0.00 1.75
0.000 1.755
0.0000 1.7550
Получается, что при float округление, делается с учетом размерности приемника + 1.
Т.е. 1,755 которая во представляется внутри как 0.7549999999999999E+00 при преобразовании к 0.00 преобразуют по факту 1.754, а не 1.755

Срочно выкидываем float отовсюду во избежании...