본문 바로가기
RAP

RAP 13 - MANAGED REPORT : VALIDATION

by SAPortal 2026. 8. 3.
반응형

 

 

 

 

 

목차

     

     

     

    APP을 실행해서 Travel 정보를 하나 생성해 보겠습니다. Create 버튼을 누르고 아래와 같이 Agency ID와 Customer ID에 마스터에 존재하지 않는 값을 입력하고 저장하면 어떻게 될까요?

     

    저장이 됩니다. 마스터에 없는 값을 실수로 입력하게 되면 문제가 될 수 있기 때문에 이를 방지해야 합니다. 이때 사용하는 기능이 Validation 입니다.

     

    VALIDATION 이란?

    사용자가 입력하거나 변경한 데이터가 비즈니스 규칙에 맞는지 검증하고, 유효하지 않을 경우 저장/진행을 막고 에러 메세지를 전달하는 로직입니다. Classic ABAP의 PAI 부분에서 필드의 값을 제어하는 부분과 유사하다고 생각하시면 됩니다.

     

     

    Interface Behavior Definition 에 아래와 같이 Validation을 추가합니다. draft 기능을 사용하기 때문에 draft determine action Prepare에도 validation을 추가해 줍니다. 추가하면 노란색 Warning이 뜹니다. Validation 로직을 구현할 Method가 없기때문입니다. 노란줄이 있는 validateCustomer 에 마우스를 클릭하고 Ctrl + 1 을 눌러 Quick Assist 기능으로 Method 를 생성합니다.

     

    Method 가 생성되었습니다. Method 명에 마우스를 올려놓고 Parameter 를 확인해 보겠습니다. keys라는 파라미터로 값이 들어오고 Travelid 필드만 존재합니다. 즉 데이터가 변경된 라인의 Travel ID가 들어오게 됩니다. 그러면 우리가 체크해야할 Customer ID값은 어떻게 알수 있을까요? 네.. 입력받은 Travel ID로 Travel Entity 를 읽으면 됩니다.

     

     

    입력받은 keys 값으로 zever_m_travel_i 엔티티를 READ 해서 그 결과를 lt_result 에 담습니다. lt_result 의 customerid 값으로 Customer 마스터를 Select 해서 lt_customer 에 담습니다.

     

     

    lt_result 를 Loop 돌면서 입력한 customerid 가 마스터에 없는값이면 failed와 reported 에 값을 넣어 에러를 리턴합니다. 메세지 처리는 메세지 클래스를 하나 만들어서 사용하겠습니다. 실제 메세지는 하드코딩을 하지 않고 Text element 를 사용하겠습니다.

     

     

    Package 에 마우스 우클릭후 New -> Other ABAP Repository Object 를 클릭합니다.

     

     

    message로 검색 후 Message Class 를 선택합니다. Next 버튼 클릭.

     

     

    Message Class Name과 Description을 입력하고 Next 버튼을 클릭합니다.

     

     

    아래와 같이 등록하고 저장해 줍니다.

     

     

    Message Class 를 생성했다면 이번에는 Text Element를 등록해 보겠습니다. 상단에 Class 텝에보면 오른쪽에 화살표 모양으로 표시된 부분이 있습니다. 클릭한 후 아래와 같이 Text Element 를 클릭합니다.

     

     

    아래와 같이 Text Element 를 등록해 줍니다. 등록 후 로직에서 사용하는 방법은 기존방식과 동일합니다. TEXT-M01 처럼 사용하면 됩니다. 

     

    validateCustomer Method의 전체소스는 아래와 같습니다.

    METHOD validateCustomer.
    
        READ ENTITIES OF zever_m_travel_i IN LOCAL MODE
        ENTITY zever_m_travel_i
        ALL FIELDS WITH CORRESPONDING #( keys )
        RESULT DATA(lt_result)
        FAILED DATA(lt_failed)
        REPORTED DATA(lt_reported).
    
        IF lt_result IS NOT INITIAL.
          SELECT a~customer_id
            FROM /dmo/customer AS a INNER JOIN @lt_result AS b ON a~customer_id = b~customerid
           ORDER BY a~customer_id
            INTO TABLE @DATA(lt_customer).
        ENDIF.
    
    
        LOOP AT lt_result INTO DATA(ls_result).
    
          IF ls_result-customerid IS NOT INITIAL.
            READ TABLE lt_customer INTO DATA(ls_customer) WITH KEY customer_id = ls_result-customerid BINARY SEARCH.
            IF sy-subrc <> 0.
              APPEND INITIAL LINE TO failed-zever_m_travel_i ASSIGNING FIELD-SYMBOL(<fs_failed>).
              <fs_failed>-%tky = ls_result-%tky.
              APPEND INITIAL LINE TO reported-zever_m_travel_i ASSIGNING FIELD-SYMBOL(<fs_reported>).
              <fs_reported>-%tky = ls_result-%tky.
              <fs_reported>-%msg = new_message( severity = if_abap_behv_message=>severity-error
                                                id       = 'ZEVER_M'
                                                number   = '000'
                                                v1       = TEXT-m01 ).
            ENDIF.
          ENDIF.
        ENDLOOP.
    
      ENDMETHOD.

     

     

    그럼 APP을 실행시켜 보겠습니다. Create 화면에서 Customer ID에 마스터에 없는 값을 입력하고 엔터를 치면 아래와 같이 에러 Popup 이 뜹니다.

     

     

    그리고 Popup을 닫으면 아래 화면이 됩니다. 뭔가 밋밋합니다. 에러가 있는 필드에 뭔가 표시를 해주면 좋을 것 같습니다. 다시 Method로 돌아가서 로직을 추가해 보겠습니다.

     

     

    %element 에 에러표시를 할 필드를 지정해 줍니다. 여기서는 custonerid 필드에 '01' 값을 주겠습니다.

     

     

    그리고 나서 다시 실행해 보면 아래와 같이 Customer ID 필드가 붉은색으로 표시되면서 에러가 표시됩니다. 그런데 여기에서 엔터를 다시한번 쳐보면... 처음처럼 에러 Popup이 뜨고 Popup을 닫으면 필드에 붉은색 표시가 다시 사라집니다. 에러가 해결될때까지 붉은색 표시를 유지하고 싶습니다. 다시 Method 에 로직을 추가해 보겠습니다.

     

     

    아래와 같이 reported 에 state_area를 지정해 줍니다. Loop시작할때 reported 에 %tky와 %state_area 만 주고 Append 하여 이전 에러메세지를 초기화 해줍니다. 그리고 에러발생시 failed를 등록하고 동일한 state_area 값으로 신규 에러메시지를 채웁니다.  

     

     

    잘못된 값 입력후 엔터를 계속 쳐도 붉은색 표시가 유지됩니다.

     

     

    Note : state_area

    동작방식 : 메시지에 %state_area 를 지정하여 등록하면 이 메시지는 일회성 팝업이 아니라 상태기반 메시지가 됩니다.
    효과 : 사용자가 다른필드를 수정하거나 다른 버튼을 눌러도 Customer ID가 올바른 값으로 수정되어 검증을 통과하기 전까지는 Fiori UI 필드의 빨간색 테두리와 에러메시지가 사라지지않고 유지 됩니다.

     

     

    이제 Agency ID 에 대한 Validation 도 구현해 보겠습니다. 아래와 같이 validation 을 추가하고 Method를 생성합니다.

     

     

    Method 의 전체소스는 아래와 같습니다.

      METHOD validateAgency.
    
        READ ENTITIES OF zever_m_travel_i IN LOCAL MODE
        ENTITY zever_m_travel_i
        ALL FIELDS WITH CORRESPONDING #( keys )
        RESULT DATA(lt_result)
        FAILED DATA(lt_failed)
        REPORTED DATA(lt_reported).
    
        IF lt_result IS NOT INITIAL.
          SELECT a~agency_id
            FROM /dmo/agency AS a INNER JOIN @lt_result AS b ON a~agency_id = b~agencyid
           ORDER BY a~agency_id
            INTO TABLE @DATA(lt_agency).
        ENDIF.
    
    
        LOOP AT lt_result INTO DATA(ls_result).
    
          APPEND INITIAL LINE TO reported-zever_m_travel_i ASSIGNING FIELD-SYMBOL(<fs_reported>).
          <fs_reported>-%tky = ls_result-%tky.
          <fs_reported>-%state_area = 'VALIDATE_AGENCY'.
    
          IF ls_result-agencyid IS NOT INITIAL.
            READ TABLE lt_agency INTO DATA(ls_agency) WITH KEY agency_id = ls_result-agencyid BINARY SEARCH.
            IF sy-subrc <> 0.
              APPEND INITIAL LINE TO failed-zever_m_travel_i ASSIGNING FIELD-SYMBOL(<fs_failed>).
              <fs_failed>-%tky = ls_result-%tky.
              APPEND INITIAL LINE TO reported-zever_m_travel_i ASSIGNING <fs_reported>.
              <fs_reported>-%tky = ls_result-%tky.
              <fs_reported>-%element-agencyid = if_abap_behv=>mk-on.
              <fs_reported>-%state_area = 'VALIDATE_AGENCY'.
              <fs_reported>-%msg = new_message( severity = if_abap_behv_message=>severity-error
                                                id       = 'ZEVER_M'
                                                number   = '000'
                                                v1       = TEXT-m02 ).
            ENDIF.
          ENDIF.
        ENDLOOP.
    
      ENDMETHOD.

     

     

    Text Element 도 등록해 줍니다.

     

     

    소스 및 Text Element 를 적용하고 App을 다시 실행해 보겠습니다. 아래와 같이 Agency ID 도 Validation 적용이 잘 되었습니다.

    Travel Status 도 동일한 방법으로 Validation 을 적용해 보시기 바랍니다. 비슷한 로직이기 때문에 이번 강의에서는 설명은 생략하겠습니다. 아 그리고 Starting Date 를 End Date 보다 크게 입력한 경우 에러처리 하는것도 한번 해보시기 바랍니다. 

     

     

    마지막으로 Booking 정보에 있는 Customer ID 필드에도 Validation 을 적용해 보겠습니다. 다시 Interface Behavior Definition 으로 가보겠습니다. 이번에는 Booking Entity 에 아래와 같이 Validation 을 추가해 줍니다. draft 기능을 사용하기 때문에 draft determine action Prepare 에도 추가해 줘야 하는데 Booking Entity에는 없는데 어떻게 해야 할까요? 

     

     

    draft 관련 action 시리즈는 Root Entity에만 존재해야 하기 때문에 아래와 같이 Entity명~Validation명 형식으로 추가해 주면 됩니다. 여기까지 추가했으면 Booking 쪽에 추가한 validation 에 대한 Method를 생성해 보겠습니다.

     

     

    Booking Entity 에서 생성한 Validation Method는 lhc_zever_m_booking_i 라는 Class 아래에 생성된 걸 볼수 있습니다. 즉 Entity별로 각각 Local Class 가 생성된다는걸 알수 있습니다. Method 구현부에 로직을 추가해 보겠습니다.

     

     

    Entity 읽는 부분과 state_area 부분이 틀려졌고 모두 똑같습니다. 한가지 주의할 부분은 Booking은 Travel 의 Child 이기 때문에 %path 정보도 아래와 같이 넘겨줘야 합니다. 

     

     

    App을 실행시켜 Booking쪽의 Customer ID에 아래와 같이 마스터에 없는 값을 입력하고 엔터를 치면 에러가 발생합니다.

     

     

     

    반응형