ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [RAP] #8 RAP Header-Item 구조의 UI 구성
    SAP/RAP 2026. 3. 3. 22:26

     

     

     

     

     

     

     

     

     

     

    Metadata Extension 파일을 활용하여 Object Page(Item Page) 구성하기

     

    1. Header Metadata Extension 파일에서 Header UI 구성 (List Report Page)

    • Object Page 구조는 Header View에서 만든다
    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        // @UI.facet을 통해 Object page 세팅
        @UI.facet: [
            { 
                id: 'SflightHeader',
                purpose: #STANDARD, // 일반 Object Page 섹션
                type: #IDENTIFICATION_REFERENCE,
                targetQualifier: 'HeaderInfo', // 어떤 Annotation 그룹을 이 facet에 연결할지 지정하는 옵션
                label: 'Header Info',
                position: 10
            },
            { 
                id: 'Booking',
                purpose: #STANDARD,
                type: #LINEITEM_REFERENCE,
                label: 'Book',
                position: 20,
                targetElement: '_Item' // Association 이름
            }
        ]
        @UI:{
            lineItem: [{ position: 10, label: '항공사' }],
            selectionField: [{ position: 10 }]
        }
        @UI.identification: [{ qualifier: 'HeaderInfo', position: 10 }]
        Carrid;
        ...
    }
    • @UI.facet : 섹션 생성 (해당 어노테이션은 필드에 붙지 않고 단독으로 사용)
      • type : #IDENTIFICATION_REFERENCE - 현재 엔티티의 필드들을 보여주는 섹션 (단일 객체 정보 표시)
                  #LINEITEM_REFERENCE - Association으로 연결된 Child 엔티티의 테이블을 보여주는 섹션
    [항공편 정보]                                IDENTIFICATION
    항공사 : LH
    편명   : 0400
    날짜   : 2024-01-01
    ------------------------
    [Book]                                    LINEITEM
    | Carrid | Connid | Bookid | ... |
    | LH     | 0400   | 001    | ... |
    | LH     | 0400   | 002    | ... |
    • @UI.identification : 현재 엔티티의 상세 정보를 Form 형태로 표시

     

    2. Item Metadata Extension 파일에서 Object Page 안의 테이블 컬럼 정의

    @Metadata.layer: #CORE
    annotate view ZSBOOK_C_B20
        with 
    {
        @UI.lineItem: [{ position: 10 }]
        Carrid;
        @UI.lineItem: [{ position: 20 }]
        Connid;
        @UI.lineItem: [{ position: 30 }]
        Fldate;
        @UI.lineItem: [{ position: 40 }]
        Bookid;
        @UI.lineItem: [{ position: 50 }]
        Customid;
        @UI.lineItem: [{ position: 60 }]
        Custtype;
        ...
        
    }

    Object Page 상단 Header 영역 구성

     

     

    Header Metadata Extension 파일

    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        // @UI.facet을 통해 Object page 세팅
        @UI.facet: [
            { // 
                id: 'SflightMainHeader',
                purpose: #HEADER,  // Object Page 상단 Header 영역
                type: #FIELDGROUP_REFERENCE, // FieldGroup을 참조
                targetQualifier: 'HeaderFG', // 어떤 FieldGroup을 연결할지 지정
                label: 'Header Info',
                position: 10
            }
        ]
        @UI:{
            ...,
            fieldGroup: [ { qualifier: 'HeaderFG', label: 'Carrier', position: 10 } ]
        }
        Carrid;
        @UI:{
            ...,
            fieldGroup: [ { qualifier: 'HeaderFG', label: 'Connection', position: 20 } ]
        }
        Connid;
        @UI:{
            ...,
            fieldGroup: [ { qualifier: 'HeaderFG', label: 'Flight Date', position: 30 } ]
        }
        Fldate;
    • FIELDGROUP_REFERENCE : 여러 필드를 하나의 그룹(Form 블록)으로 묶어 표시하는 방식
    • @UI.fieldGroup : 특정 그룹에 필드 삽입
      • @UI.fieldGroup + #HEADER → 구조화된 Header

    Object Page Body 영역에서 Identification Section 구성

    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        // @UI.facet을 통해 Object page 세팅
        @UI.facet: [
            ...,
            { 
                id: 'SflightHeader',
                purpose: #STANDARD,
                type: #IDENTIFICATION_REFERENCE,
                targetQualifier: 'Identification1',
                label: 'Header Info',
                position: 10
            },
            { 
                id: 'SflightHeader_seasts',
                purpose: #STANDARD,
                type: #IDENTIFICATION_REFERENCE,
                targetQualifier: 'Identification2',
                label: 'Flight Info - Seats',
                position: 20
            },
            ...
        ]
        
        // Identification1
        @UI.identification: [ { qualifier: 'Identification1', position: 10 } ]
        Carrid;
        @UI.identification: [{ qualifier: 'Identification1', position: 30 }]
        Fldate;
        @UI.identification: [{ qualifier: 'Identification1', position: 40 }]
        Price;
        @UI.identification: [{ qualifier: 'Identification1', position: 50}]
        Currency;
    
        // Identification2
        @UI.identification: [ { qualifier: 'Identification2', position: 10 } ]    
        Seatsmax;
        @UI.identification: [{ qualifier: 'Identification2', position: 30, label: 'SeatsOcc' }]
        Seatsocc;
        @UI.identification: [{ qualifier: 'Identification2', position: 30, label: 'Business Max' }]
        SeatsmaxB;
        @UI.identification: [{ qualifier: 'Identification2', position: 40, label: 'Business Occ' }]
        SeatsoccB;
        @UI.identification: [{ qualifier: 'Identification2', position: 50, label: 'First Max' }]
        SeatsmaxF;
        @UI.identification: [{ qualifier: 'Identification2', position: 60, label: 'First Occ' }]
        SeatsoccF;
    }

    텍스트 색상 처리 및 아이콘

     

    1. Interface View

    @AccessControl.authorizationCheck: #NOT_REQUIRED
    @EndUserText.label: 'Interface View(root)'
    @Metadata.ignorePropagatedAnnotations: true
    define root view entity ZSFLIGHT_IR_B20 as select from sflight as sf
        composition[0..*] of ZSBOOK_I_B20 as _Item
        association to scarr as _Scarr
        on $projection.Carrid = _Scarr.carrid
    
    {
        ...
        seatsmax as Seatsmax,
        seatsocc as Seatsocc,
        seatsmax - seatsocc as Seatsremain,
        case
            when $projection.Seatsremain > 50 then 3  // green
            when $projection.Seatsremain > 20 then 2  // yellow
            when $projection.Seatsremain > 0 then 1   // red
            else 0 // unknown
        end as SeatsremainCriticality, // 색상코드 필드
       ...
    }

     

    2. Projection View

    ...
    define root view entity ZSFLIGHT_CR_B20
        as projection on ZSFLIGHT_IR_B20
    {
        ...
        Seatsremain, // 남은 좌석수 필드 추가
        SeatsremainCriticality, // 남은 좌석수 필드에 따른 색상코드 필드 추가
        ...
    }

     

    3. Metadata Extension

    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        ...
        @UI:{
            lineItem: [{ 
                position: 90, label: '잔여석', 
                criticality: 'SeatsremainCriticality',    // 색상을 결정할 필드 지정
                criticalityRepresentation: #WITHOUT_ICON  // 아이콘 없이 색상만
            }]
        }
        Seatsremain;
    }

     


    Object Page Header 영역에서 Criticality/Datapoint 구성

    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        @UI.facet: [
            { 
                id: 'SflightSeatsRemain',
                purpose: #HEADER,
                type : #DATAPOINT_REFERENCE,  // 데이터 포인트(KPI) 표시
                targetQualifier: 'HeaderState',
                position: 20
            }
        ]
    
        @UI:{
            lineItem: [{ 
                position: 90, label: '잔여석', 
                criticality: 'SeatsremainCriticality',
                criticalityRepresentation: #WITHOUT_ICON
            }],
            identification: [{ qualifier: 'Identification2', position: 70, label: '잔여석'}],
            dataPoint: { 
               title: '남은 좌석 수', 
               qualifier: 'HeaderState', 
               criticality: 'SeatsremainCriticality' // 색상/상태 기준 필드
            }
        }
        Seatsremain;
    
    }
    • @UI.dataPoint : Object Page Header 또는 KPI 카드에 표시되는 핵심 상태 값

    Object Page Header 영역에서 차트 구성

     

    1. Interface View

    @AccessControl.authorizationCheck: #NOT_REQUIRED
    @EndUserText.label: 'Interface View(root)'
    @Metadata.ignorePropagatedAnnotations: true
    define root view entity ZSFLIGHT_IR_B20 as select from sflight as sf
        composition[0..*] of ZSBOOK_I_B20 as _Item
        association to scarr as _Scarr
        on $projection.Carrid = _Scarr.carrid
    
    {
    	...
        cast(
            cast(seatsocc as abap.fltp) / cast(seatsmax as abap.fltp) * 100.0 as abap.dec(15, 2)
        ) as Percentage,
        case
            when $projection.Percentage = 100 then 3  // green
            when $projection.Percentage > 50 then 2  // yellow
            when $projection.Percentage > 0 then 1   // red
            else 0 // unknown
        end as PercentageCriticality, // 색상코드 필드
        
    
    }

     

    2. Projection View

    ...
    define root view entity ZSFLIGHT_CR_B20
        as projection on ZSFLIGHT_IR_B20
    {
        ...
        Percentage, // 예약율 필드 추가
        PercentageCriticality, // 예약율에 따른 색상코드 필드 추가
        ...
    }

     

    3. Metadata Extension

    ...
    annotate view ZSFLIGHT_CR_B20
        with 
    {
    
       @UI.facet: [
            { 
                id: 'SflightPercentage',
                purpose: #HEADER,
                type : #DATAPOINT_REFERENCE, // 데이터 포인트(KPI) 표시
                targetQualifier: 'HeaderPercent',
                position: 30
            }
        ]
    
        @UI.lineItem: [{ 
            position: 100, 
            label: '예약율(%)', 
            type: #AS_DATAPOINT // DataPoint 형태 지정
        }]
        @UI.dataPoint: { 
            title: '예약율 (%)',
            description: '좌석수를 이용해 계산한 결과값',
            qualifier: 'HeaderPercent',
            visualization: #PROGRESS, // Progress Bar
            targetValue: 100,  // 최대 값 기준
            criticality: 'PercentageCriticality' // 색상제어 ( 1:Red, 2: Yellow, 3:Green )
        }
        Percentage;
    
    }

    테이블 컬럼 영역에서 차트 구성

     

    1. Interface View

    @AccessControl.authorizationCheck: #NOT_REQUIRED
    @EndUserText.label: 'Interface View(root)'
    @Metadata.ignorePropagatedAnnotations: true
    define root view entity ZSFLIGHT_IR_B20 as select from sflight as sf
        composition[0..*] of ZSBOOK_I_B20 as _Item
        association to scarr as _Scarr
        on $projection.Carrid = _Scarr.carrid
    
    {
        ...
        // 1. 현재 총 수익 (예약석 * 단가)
        @Aggregation.default: #SUM // UI상에서 동적 합계 적용
        @Semantics.amount.currencyCode: 'Currency'
        cast(
            cast( price as abap.fltp ) * cast( seatsocc as abap.fltp ) as abap.dec(15,2) 
        ) as CurrentRevenue,
        case
            when $projection.CurrentRevenue > 95 then 3 // green
            when $projection.CurrentRevenue > 20 then 2 // yellow
            when $projection.CurrentRevenue > 10 then 1 // red
            else 0 // unknown
          end as RevenueCriticality, // 색상코드 필드
        
        // 2. 최대 잠재 수익 (전체 좌석수 * 단가)
        @Aggregation.default: #SUM // UI상에서 동적 합계 적용
        @Semantics.amount.currencyCode: 'Currency'
        cast(
            cast( price as abap.fltp ) * cast( seatsmax as abap.fltp ) as abap.dec(15,2) 
        ) as MaxRevenue,
       ...
    }

     

    2. Projection View

    ...
    define root view entity ZSFLIGHT_CR_B20
        as projection on ZSFLIGHT_IR_B20
    {
        ...
        CurrentRevenue, // (예약수에 따른) 현재 수익
        RevenueCriticality,
        MaxRevenue, // (만석시) 총 수익
        ...
    }

     

    3. Metadata Extension

    ...
    @UI.chart: [
        { 
            qualifier: 'RevenueChart',
            title: '수익 현황',
            chartType: #DONUT,
            measures: [ 'CurrentRevenue' ], //현재 수익
            measureAttributes: [ {  
                measure: 'CurrentRevenue',  // 차트에 표시될 데이터 필드
                asDataPoint: true  // DataPoint 설정을 사용하겠다.
            } ]
        }
    ]
    annotate view ZSFLIGHT_CR_B20
        with 
    {
        
        @UI.lineItem:[{ 
            position: 110, 
            type: #AS_CHART,  // Projection View 테이블 컬럼에 차트 표시
            label: '수익 달성도', 
            valueQualifier: 'RevenueChart' 
        }]
        @UI.dataPoint: { 
            targetValueElement: 'MaxRevenue', // 목표값
            forecastValue: 'CurrentRevenue'   // 현재값
            //criticality : 'RevenueCriticality' 색상제어 가능
        }
        CurrentRevenue;
        
        
    }
    • @Aggregation.default: #SUM → Fiori UI에서 테이블 컬럼 합계 표시 가능

     

     

     

     

     

     

    'SAP > RAP' 카테고리의 다른 글

    [RAP] #7 Annotation 정리  (1) 2026.03.03
    [RAP] #6 RAP  (0) 2026.03.01
    [RAP] #5 CDS View 추가 문법 (2)  (0) 2026.02.26
    [RAP] #4 CDS View 추가 문법 (1)  (0) 2026.02.25
    [RAP] #2 CDS View  (0) 2026.02.22
Designed by Tistory.