ABAP

QAMV 없이 검사 결과 조회 3가지 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요 및 이 글에서 다루는 것

SAP S/4HANA 환경에서 품질 관리(QM) 데이터를 분석하거나 확장 앱을 개발할 때, 검사 특성 결과(Inspection Characteristic Result)는 가장 자주 참조되는 데이터입니다. 과거 ECC 시절부터 개발자들은 QAMV, QAMR, QALS 테이블을 직접 조인해왔지만, S/4HANA Cloud 및 On-Premise Embedded Steampunk 환경에서는 이러한 직접 접근이 권장되지 않습니다. 이 글은 표준 CDS View인I_InspectionCharacteristicResult를 활용해 QAMV 없이도 동일한(혹은 더 나은) 결과를 얻는 실전 예제를 다룹니다.

  • QAMV 직접 조회의 구조적 문제와 릴리스 정책 이해
  • I_InspectionCharacteristicResult CDS View의 구조·주요 필드 파악
  • ABAP, OData, AMDP 세 가지 접근 패턴 구현
  • Association 기반의 검사 로트/텍스트 연계 조회
  • 대량 데이터 상황에서의 성능 최적화 전략

사전에 알고 있어야 할 것

이 글은 advanced 난이도로, 다음 사항을 이미 이해하고 있다고 가정합니다. ABAP CDS View 기본 문법(define view entity, association, annotation), SAP QM 모듈의 검사 로트/특성 개념(Inspection Lot, Characteristic, Valuation), SELECT 문의 조인·서브쿼리, ABAP for Cloud Development 릴리스 상태(C1/C2)의 의미. QAMV, QALS, QASR 등 클래식 QM 테이블의 존재 자체는 알고 있으면 좋습니다.

실습 환경과 준비물

이 글의 예제는 다음 환경을 기준으로 작성되었습니다.

  • SAP S/4HANA 2022 On-Premise 또는 SAP S/4HANA Cloud Public Edition 2402 이상
  • ABAP Development Tools (ADT) for Eclipse 2024-03 이상
  • ABAP RESTful Application Programming Model(RAP) 사용 가능 시스템
  • 권한: S_RS_AUTH, Q_TCODE (검사 로트 조회용), CDS 조회를 위한 S_RS_AUTH
  • 테스트 데이터: 활성화된 검사 로트(Inspection Lot Origin 04 - 생산 오더 기반) 최소 1건

Cloud 환경에서는 I_InspectionCharacteristicResult가 릴리스 계약(C1 Public API 또는 C2 Extension)에 따라 사용 가능한 필드가 다를 수 있으므로, ADT에서 View를 열어 릴리스 상태를 반드시 확인해야 합니다.

QAMV 직접 조회의 한계와 CDS View 접근의 원리

QAMV(검사 특성 결과값), QAMR(검사 결과 참조), QALS(검사 로트), QASR(요약 결과) 네 테이블은 물리적으로는 여전히 존재하지만, S/4HANA에서는 다음과 같은 문제를 야기합니다.

QAMV는 클라이언트 종속(MANDT), 로트/특성/샘플/응답별 다중 키(PRUEFLOS, MERKNR, VERSION, PROBENR, WERTNR)를 가지며, 실제 결과값은 QASR·QAMR에 분산 저장됩니다. 텍스트, 코드 그룹, 평가 상태 등 부가 정보를 얻으려면 최소 4~6개 테이블 조인이 필요합니다.

비유하자면 QAMV 직접 조회는 "공장 배전반의 개별 회로를 하나씩 뜯어 전압을 재는 것"과 같고, I_InspectionCharacteristicResult"이미 통합된 계기판에서 값을 읽는 것"과 같습니다.

I_InspectionCharacteristicResult CDS View는 다음 구조로 이러한 복잡성을 캡슐화합니다.

  • 키 필드: InspectionLot, InspectionCharacteristic, InspectionCharcVersion, InspectionCharcSample
  • 결과 필드: InspectionResultValuation(평가 A/R), InspResultMeanValue(평균), InspResultNonConformingUnits(불합격 단위)
  • 상태 필드: InspCharacteristicIsCompleted, InspCharcResultIsRejected
  • Association: _InspectionLot, _InspectionCharacteristic, _Plant, _Material

여기에 관리자가 CDS annotation(@Consumption.filter, @AccessControl.authorizationCheck)을 통해 자동으로 부여한 권한 필터가 SELECT 시점에 적용되므로, 개발자가 별도로 AUTHORITY-CHECK를 코딩할 필요가 없어집니다. 이것이 QAMV 대비 가장 큰 실무적 이점입니다.

실전 예제 1단계 — 기본 조회 패턴

먼저 특정 공장(Plant)의 최근 검사 로트에 대해 불합격 처리된 검사 특성을 조회하는 가장 단순한 형태입니다. 시나리오는 자동차 부품 제조사가 "생산 라인 P-102에서 지난 30일간 불합격 판정된 검사 특성"을 확인하려는 경우입니다.

DATA lt_reject_charc TYPE TABLE OF i_inspectioncharacteristicresult.

SELECT InspectionLot,
       InspectionCharacteristic,
       InspectionCharcVersion,
       InspectionResultValuation,
       InspResultNonConformingUnits,
       InspCharcResultIsRejected
  FROM I_InspectionCharacteristicResult
  WHERE InspectionResultValuation = 'R'
    AND InspCharcResultIsRejected = abap_true
    AND InspectionLotCreationDate >= @( cl_abap_context_info=>get_system_date( ) - 30 )
  INTO TABLE @lt_reject_charc
  UP TO 500 ROWS.

cl_demo_output=>display( lt_reject_charc ).

QAMV로 같은 결과를 얻으려면 QALS(로트 헤더), QAMV(특성값), QAVE(평가 코드) 조인이 필수였습니다. CDS View는 이러한 조인을 내부적으로 처리합니다.

실전 예제 2단계 — 생산 오더 기반 집계와 로깅

이제 실무 시나리오로 확장합니다. 특정 생산 오더(Manufacturing Order) 번호를 입력받아, 해당 오더에 연결된 모든 검사 로트의 특성별 불합격 현황을 집계하고, Application Log(BAL_LOG)에 기록합니다. Association을 활용해 검사 로트 헤더에서 오더 번호를 필터링하는 것이 핵심입니다.

CLASS zcl_qm_charc_analyzer DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_charc_summary,
             manufacturing_order TYPE aufnr,
             inspection_lot      TYPE qplos,
             characteristic      TYPE qmerknr,
             rejected_units      TYPE qamv-fehleranteil,
             valuation_text      TYPE string,
           END OF ty_charc_summary,
           tt_charc_summary TYPE STANDARD TABLE OF ty_charc_summary WITH EMPTY KEY.

    METHODS analyze
      IMPORTING iv_order          TYPE aufnr
      RETURNING VALUE(rt_summary) TYPE tt_charc_summary
      RAISING   cx_abap_invalid_value.
ENDCLASS.

CLASS zcl_qm_charc_analyzer IMPLEMENTATION.
  METHOD analyze.
    IF iv_order IS INITIAL.
      RAISE EXCEPTION TYPE cx_abap_invalid_value
        EXPORTING textid = cx_abap_invalid_value=>parameter_invalid.
    ENDIF.

    TRY.
        SELECT icr~InspectionLot,
               lot~ManufacturingOrder,
               icr~InspectionCharacteristic,
               icr~InspResultNonConformingUnits,
               icr~InspectionResultValuation
          FROM I_InspectionCharacteristicResult AS icr
          INNER JOIN I_InspectionLot AS lot
            ON icr~InspectionLot = lot~InspectionLot
          WHERE lot~ManufacturingOrder = @iv_order
            AND icr~InspCharcResultIsRejected = @abap_true
          INTO TABLE @DATA(lt_raw).

        rt_summary = VALUE #(
          FOR ls IN lt_raw
          ( manufacturing_order = ls-ManufacturingOrder
            inspection_lot      = ls-InspectionLot
            characteristic      = ls-InspectionCharacteristic
            rejected_units      = ls-InspResultNonConformingUnits
            valuation_text      = COND #(
              WHEN ls-InspectionResultValuation = 'R' THEN 'Rejected'
              WHEN ls-InspectionResultValuation = 'A' THEN 'Accepted'
              ELSE 'Undefined' ) ) ).

      CATCH cx_sy_open_sql_db INTO DATA(lx_db).
        cl_bali_message_setter=>create(
          severity = if_bali_constants=>c_severity_error
          text     = lx_db->get_text( ) )->add_to_log(
            log = cl_bali_log=>create_with_header(
              header = cl_bali_header_setter=>create(
                object     = 'ZQM'
                subobject  = 'CHARC_QUERY' ) ) ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

실전 예제 3단계 — 프로덕션급 AMDP와 OData 노출

대량 데이터(수십만 건 이상)를 다루는 대시보드 서비스라면 AMDP(ABAP Managed Database Procedure)로 HANA 푸시다운을 활용하는 것이 일반적으로 권장됩니다. 아래는 공장별·자재별 불합격률을 계산하는 AMDP 예제입니다.

CLASS zcl_qm_charc_kpi DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_kpi,
             plant             TYPE werks_d,
             material          TYPE matnr,
             total_charc       TYPE int4,
             rejected_charc    TYPE int4,
             reject_ratio      TYPE p LENGTH 5 DECIMALS 2,
           END OF ty_kpi,
           tt_kpi TYPE STANDARD TABLE OF ty_kpi WITH EMPTY KEY.

    INTERFACES if_amdp_marker_hdb.

    CLASS-METHODS calc_reject_ratio
      IMPORTING VALUE(iv_from_date) TYPE dats
                VALUE(iv_plant)     TYPE werks_d
      EXPORTING VALUE(et_kpi)       TYPE tt_kpi.
ENDCLASS.

CLASS zcl_qm_charc_kpi IMPLEMENTATION.
  METHOD calc_reject_ratio BY DATABASE PROCEDURE
    FOR HDB LANGUAGE SQLSCRIPT
    OPTIONS READ-ONLY
    USING i_inspectioncharacteristicresult i_inspectionlot.

    et_kpi = SELECT lot.plant           AS plant,
                    lot.material        AS material,
                    COUNT(*)            AS total_charc,
                    SUM( CASE WHEN icr.inspcharcresultisrejected = 'X'
                              THEN 1 ELSE 0 END ) AS rejected_charc,
                    ROUND( SUM( CASE WHEN icr.inspcharcresultisrejected = 'X'
                              THEN 1 ELSE 0 END ) * 100.0 / COUNT(*), 2 ) AS reject_ratio
               FROM i_inspectioncharacteristicresult AS icr
               INNER JOIN i_inspectionlot AS lot
                 ON icr.inspectionlot = lot.inspectionlot
              WHERE lot.plant = :iv_plant
                AND lot.inspectionlotcreationdate >= :iv_from_date
              GROUP BY lot.plant, lot.material;

  ENDMETHOD.
ENDCLASS.

OData로 외부에 노출할 때는 RAP Projection View를 정의합니다.

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Rejected Characteristic Projection'
define root view entity ZC_RejectedCharc
  provider contract transactional_query
  as projection on I_InspectionCharacteristicResult
{
  key InspectionLot,
  key InspectionCharacteristic,
      InspectionResultValuation,
      InspResultNonConformingUnits,
      InspCharcResultIsRejected,
      _InspectionLot.ManufacturingOrder,
      _InspectionLot.Plant,
      _InspectionLot.Material
}
where InspCharcResultIsRejected = 'X';

자주 겪는 오류와 해결 팁

Q1. "View I_InspectionCharacteristicResult is not released for cloud development" 오류
ABAP for Cloud 프로젝트에서는 릴리스 계약이 C1 이상이어야 합니다. ADT에서 View를 열고 Properties → API State를 확인하세요. C2(Extension)로만 릴리스되었다면 Projection View를 자체 개발해 감싸는 방법이 일반적입니다.

Q2. 결과 건수가 QAMV 직접 SELECT보다 적습니다.
CDS View는 삭제 플래그(LOEKZ), 클라이언트, 권한 필터를 자동 적용합니다. (1) 사용자 권한 부족, (2) 로트 상태가 미완료, (3) 특성 버전이 최신이 아님을 순서대로 점검하세요.

Q3. 대량 조회 시 타임아웃이 발생합니다.
InspectionLotCreationDate는 인덱스 필드입니다. WHERE 절 맨 앞에 두고 Plant와 함께 사용하세요. AMDP 또는 PACKAGE SIZE로 분할 처리를 권장합니다.

흔한 실수 유형: (1) _InspectionLot.Plant를 SELECT 리스트에만 두고 WHERE에 사용하지 않아 조인이 뒤늦게 실행, (2) InspCharcResultIsRejectedchar1이라 abap_true('X') 대신 공백 비교로 잘못 필터링, (3) InspectionCharcSample 키를 무시해 중복 집계 발생.

이어서 탐색하면 좋은 주제

  • I_InspectionLot, I_InspectionCharacteristicText, I_QualityNotification과의 Association 확장
  • SAP Analytics Cloud와 연동한 QM KPI 대시보드 구축(Live Connection)
  • Embedded Steampunk에서 RAP BO로 검사 결과 조회 서비스 구현
  • Behavior Definition을 통한 검사 특성 결과의 Read-only 서비스화
  • CDS Table Function으로 QAMV/QAMR 커스텀 필드 매핑(레거시 확장 필드)

정리하면, QAMV 직접 조회는 여전히 기술적으로 가능하지만 유지보수·클라우드 호환·권한 처리 측면에서 I_InspectionCharacteristicResult가 일반적으로 권장됩니다. S/4HANA Cloud 전환을 계획 중인 시스템이라면 초기 개발 단계부터 CDS View 기반으로 접근 계층을 통일해두는 것이 장기적으로 유리합니다.

댓글 0

아직 댓글이 없습니다.