📖 개요 — 이 글에서 다루는 것
SAP SD에서 판매 문서의 단가가 "어디서, 어떤 규칙으로" 튀어나오는지 추적할 수 있는 사람은 의외로 적습니다. 그 비밀은 Condition Technique(조건 기법)이라는 5요소 구조에 있습니다. 이 글은 견적(Quotation)과 수주(Sales Order)에서 판매가가 결정되는 과정을 가격결정절차(Pricing Procedure) → 조건유형(Condition Type) → 접근순서(Access Sequence) → 조건표(Condition Table) → 조건레코드(Condition Record) 순으로 한 단계씩 따라가며 해부합니다. 읽고 나면 다음을 할 수 있습니다.
- 수주 화면의 가격 분석(Pricing Analysis)에서 각 조건값의 출처를 역추적할 수 있다
- 커스텀 조건유형과 접근순서를 직접 설계하고 IMG에서 구성할 수 있다
- 조건레코드가 안 잡히는 상황(가격 미결정 오류)을 체계적으로 진단할 수 있다
- 커스텀 필드를 가격결정 통신구조에 추가해 실무 요구를 구현할 수 있다
📚 미리 알고 있으면 좋은 배경
SD 판매 문서(견적/수주)의 기본 흐름, 즉 판매조직·유통채널·오더유형이 무엇인지 알고 있어야 합니다. IMG(SPRO) 구성 경험이 있으면 좋고, 3단계 예제의 ABAP 코드를 이해하려면 기초 ABAP 문법(SELECT, 구조체)이 필요합니다. 조건 기법 자체는 SD 가격뿐 아니라 출력결정, 자재결정, 배치결정에도 쓰이는 범용 프레임워크이므로, 이 글의 구조를 이해하면 다른 결정 로직에도 그대로 응용됩니다.
🔧 환경 / 버전 / 준비물
이 글의 예제는 SAP S/4HANA 2023 (On-Premise) 기준으로 작성했으며, 개념 구조는 SAP ECC 6.0에서도 동일합니다. 다만 저장 테이블에 차이가 있습니다. ECC에서는 문서의 조건 결과가 KONV 테이블에 저장되지만, S/4HANA에서는 PRCD_ELEMENTS로 대체되었습니다(호환 뷰 V_KONV 제공). 준비물은 다음과 같습니다.
- IMG 구성 권한이 있는 개발/샌드박스 클라이언트
- 주요 트랜잭션: V/03~V/05(조건표), V/07(접근순서), V/06(조건유형), V/08(가격결정절차), OVKK(절차 결정), VK11/VK12/VK13(조건레코드 유지/조회)
- 마스터 데이터: 판매조직·유통채널·자재·거래처가 세팅된 상태
- 조건레코드의 원본 마스터 테이블은 Axxx(조건표별 생성), 헤더/항목은 KONH/KONP — 디버깅 시 참고
💡 핵심 개념 — 5요소가 맞물리는 방식
Condition Technique를 비유하자면 "도서관에서 책 찾기"와 같습니다. 다섯 요소의 역할을 대응시켜 보면 이렇게 됩니다.
- 가격결정절차(Pricing Procedure) = 읽어야 할 책의 목록표. 어떤 조건유형을 어떤 순서(Step/Counter)로 계산할지, 어떤 값을 소계(Subtotal)로 남길지, 특정 단계를 건너뛸 조건(Requirement)은 무엇인지 정의합니다. 표준 예로 RVAA01이 있습니다.
- 조건유형(Condition Type) = 책 한 권의 성격. 기본가인지 할인인지 할증인지, 백분율인지 정액인지, 수량 스케일을 쓰는지 정의합니다. 표준 PR00(기본가), K004(자재 할인) 같은 것이 여기에 해당합니다.
- 접근순서(Access Sequence) = 서가를 뒤지는 순서. "이 책을 찾을 때 1층 특별서가부터 보고, 없으면 일반서가로 가라"는 탐색 전략입니다. 구체적(specific) 조건표에서 일반적(general) 조건표 순서로 배열하는 것이 일반적인 설계 원칙입니다.
- 조건표(Condition Table) = 서가 하나. 어떤 키 필드 조합(예: 판매조직+유통채널+거래처+자재)으로 값을 저장할지 정의합니다. 저장하면 실제 DB 테이블 Annn이 생성됩니다.
- 조건레코드(Condition Record) = 서가에 꽂힌 실제 책. "이 거래처가 이 자재를 사면 EA당 12,000원" 같은 실데이터로, VK11로 유효기간과 함께 생성합니다.
런타임 동작 순서는 위 나열의 역방향이 아니라 절차부터 시작합니다. 수주를 저장하는 순간 시스템은 (1) 판매영역+거래처 가격결정절차키+문서 가격결정절차키 조합으로 절차를 결정하고(OVKK), (2) 절차 안의 조건유형을 Step 순서대로 훑으며, (3) 각 조건유형에 연결된 접근순서를 따라, (4) 조건표를 하나씩 조회하고, (5) 유효한 조건레코드를 찾는 즉시 값을 가져옵니다. 접근에 배타(Exclusive) 표시가 있으면 첫 히트에서 탐색을 멈춥니다. 이때 문서의 헤더/항목 데이터는 통신구조 KOMK(헤더)와 KOMP(항목)에 담겨 조건표 키 필드와 매핑됩니다. 즉 "조건표의 키 필드 값을 KOMK/KOMP에서 채워 Annn 테이블을 SELECT한다"가 조건 기법의 물리적 실체입니다.
💻 실전 예제 — 조명 제조사 딜러 가격 체계 만들기
가상의 조명 제조사 "한빛라이팅"이 딜러망에 판매하는 시나리오로 처음부터 끝까지 만들어 봅니다. 요구사항: 딜러별 특별단가가 있으면 그것을 쓰고, 없으면 채널 표준단가를 적용한다. 여기에 딜러 등급 할인을 얹는다.
1단계 — 기본 구성: 5요소를 바닥부터 쌓기
커스텀 조건표 두 개(딜러+자재 / 판매조직+유통채널+자재), 접근순서, 조건유형, 절차를 만듭니다. 조건표 번호는 501~999 커스텀 영역을 사용합니다.
* IMG 구성 요약 (SPRO > 판매및유통 > 기본기능 > 가격결정)
* --- (1) 조건표: V/03 ---
* 조건표 921 : VKORG / VTWEG / KUNNR / MATNR (딜러별 특별단가용)
* 조건표 922 : VKORG / VTWEG / MATNR (채널 표준단가용)
* → 저장 시 DB 테이블 A921, A922 자동 생성
* --- (2) 접근순서: V/07 ---
* 접근순서 ZHBP
* AcNo 10 조건표 921 배타(Exclusive) = X "딜러 특별단가 우선"
* AcNo 20 조건표 922 "없으면 채널 표준단가"
* --- (3) 조건유형: V/06 ---
* ZHBP 한빛 기본단가 : 조건범주 기본가, 계산유형 C(수량),
* 접근순서 ZHBP, 수동입력 우선 아님
* ZHDG 딜러등급할인 : 계산유형 A(백분율), 음수(할인),
* 접근순서 ZHDG(조건표 923: VKORG/ZZDLGR)
* --- (4) 가격결정절차: V/08 ---
* 절차 ZHBLT1
* Step 100 ZHBP 필수(Required) = X
* Step 200 ZHDG
* Step 300 소계 '순가' (Subtotal)
* --- (5) 절차 결정: OVKK ---
* 1000/10/00 + 문서절차 A + 고객절차 1 → ZHBLT1
이제 VK11로 조건레코드를 넣습니다. 조건유형 ZHBP, 키 조합 선택 화면에서 921 테이블을 고르면: 판매조직 1000 / 채널 10 / 딜러 HB-DLR-0042 / 자재 LT-PANEL-60W → 단가 11,500 KRW/EA, 유효기간 2026.01.01~2026.12.31. 이후 견적(VA21)이나 수주(VA01)에서 이 딜러와 자재를 입력하면 항목 조건 탭에 ZHBP 11,500원이 자동으로 잡힙니다. 항목 조건 화면의 "분석(Analysis)" 버튼을 누르면 접근순서 ZHBP가 921을 먼저 조회해 히트했고 922는 배타 규칙으로 건너뛰었다는 로그를 그대로 볼 수 있습니다. 이 분석 화면이 조건 기법 디버깅의 시작점입니다.
2단계 — 실무 시나리오: 요구조건 루틴과 가격 추적 리포트
실무에서는 "딜러등급할인 ZHDG는 반품 오더에서는 적용하지 말라" 같은 요구가 붙습니다. 절차의 해당 Step에 Requirement(요구조건) 루틴을 걸어 해결합니다. VOFM(요구조건 > 가격결정)에서 커스텀 루틴 901번을 생성합니다.
* VOFM 요구조건 901 (생성 프로그램: RV61A901)
FORM kobed_901.
sy-subrc = 4. " 기본값: 조건 미적용
" 반품 오더유형이면 할인 스킵
IF komk-auart = 'ZHRE'. " 한빛 반품 오더유형(창작)
RETURN.
ENDIF.
" 딜러 등급 필드가 비어 있으면 로그 남기고 스킵
IF komk-zzdlgr IS INITIAL.
" 가격 분석 화면에서 원인 확인 가능하도록 명시적 종료
RETURN.
ENDIF.
sy-subrc = 0. " 조건 적용
ENDFORM.
FORM kobev_901. " 사전 체크(성능용 선행 판정)
sy-subrc = 0.
ENDFORM.
또 하나 자주 필요한 것이 "이 수주의 가격이 어떤 조건레코드에서 왔는가"를 사후 추적하는 리포트입니다. S/4HANA에서는 PRCD_ELEMENTS를 읽습니다.
REPORT zhb_price_trace.
PARAMETERS pv_vbeln TYPE vbeln_va OBLIGATORY.
SELECT vd~knumv INTO @DATA(lv_knumv)
FROM vbak AS vd WHERE vbeln = @pv_vbeln.
ENDSELECT.
IF sy-subrc <> 0.
MESSAGE '수주를 찾을 수 없습니다' TYPE 'E'.
ENDIF.
SELECT kposn, kschl, knumh, kbetr, waers, kwert
FROM prcd_elements " ECC라면 KONV
WHERE knumv = @lv_knumv
AND kinak = @space " 비활성 조건 제외
INTO TABLE @DATA(lt_cond).
LOOP AT lt_cond INTO DATA(ls_cond).
" knumh가 있으면 조건레코드 유래, 없으면 수동/자동계산 조건
IF ls_cond-knumh IS NOT INITIAL.
WRITE: / ls_cond-kposn, ls_cond-kschl,
'레코드', ls_cond-knumh, ls_cond-kbetr, ls_cond-waers.
ELSE.
WRITE: / ls_cond-kposn, ls_cond-kschl, '수동/파생', ls_cond-kwert.
ENDIF.
ENDLOOP.
KNUMH를 키로 KONH/KONP를 조회하면 유효기간·스케일까지 역추적할 수 있어, "왜 이 단가가 나왔죠?"라는 영업의 질문에 근거를 제시할 수 있습니다.
3단계 — 프로덕션: 커스텀 필드, 성능, 권한
2단계의 ZZDLGR(딜러 등급)은 표준 필드가 아니므로, 조건표 필드 카탈로그에 추가하고 통신구조 KOMK에 값을 채워야 합니다. 필드 카탈로그 추가는 KOMKAZ(헤더 확장 인클루드)에 ZZDLGR을 append 하고, 값 채우기는 MV45AFZZ의 USEREXIT_PRICING_PREPARE_TKOMK에서 처리합니다(S/4HANA On-Premise에서도 이 유저이그짓은 유효하게 동작합니다).
* MV45AFZZ - USEREXIT_PRICING_PREPARE_TKOMK
FORM userexit_pricing_prepare_tkomk.
" 거래처 마스터 확장 테이블(창작)에서 딜러 등급 조회
SELECT SINGLE zzdlgr FROM zhb_dealer_attr
WHERE kunnr = @tkomk-kunnr
INTO @tkomk-zzdlgr.
IF sy-subrc <> 0.
CLEAR tkomk-zzdlgr. " 미등록 딜러: 요구조건 901이 할인 스킵
ENDIF.
ENDFORM.
프로덕션 관점 체크리스트는 세 가지입니다. 첫째 성능 — 접근순서의 접근 개수만큼 매 항목마다 Annn SELECT가 발생하므로, 히트 확률이 높은 접근에 배타 표시를 걸고, 거의 쓰지 않는 조건표는 접근에서 제거합니다. 조건유형 V/06의 사전단계(KOBEV) 루틴으로 불필요한 접근 자체를 차단하는 것도 유효합니다. 둘째 테스트 — 조건레코드 유효기간 경계(시작 전날/종료 다음날), 스케일 경계 수량, 요구조건 분기(반품/일반)를 케이스로 만들어 가격 분석 화면 캡처와 함께 이관 문서에 남기는 것이 권장됩니다. 셋째 보안 — 조건레코드 유지(VK11/VK12)는 단가를 바꾸는 행위이므로 권한 객체 V_KONH_VKS(조건유형별)와 V_KONH_VKO(판매영역별)로 영업기획 팀에만 부여하고, 변경 이력은 조건레코드 변경문서로 감사 추적하도록 운영 절차를 잡습니다.
⚠️ 흔한 실수와 트러블슈팅
- Q1. 조건레코드를 만들었는데 수주에 안 잡힙니다. 가장 흔한 4대 원인: (1) 문서 가격결정일자가 레코드 유효기간 밖 — 수주의 Pricing Date를 확인하세요. (2) 절차 결정 불일치 — OVKK 조합이 다른 절차를 골랐을 수 있습니다. (3) 접근순서의 키 필드에 값이 비어 있음 — 가격 분석 화면에서 "접근이 수행되지 않음" 메시지와 누락 필드를 확인합니다. (4) 요구조건 루틴이 sy-subrc = 4로 빠짐 — 루틴 로직을 점검합니다.
- Q2. 딜러 특별단가와 채널 표준단가가 동시에 둘 다 잡힙니다. 접근순서에서 상위 접근의 배타(Exclusive) 체크가 빠진 경우입니다. 배타가 없으면 히트해도 다음 접근을 계속 조회해 같은 조건유형에 복수 값이 생길 수 있습니다.
- Q3. 커스텀 필드 ZZDLGR을 조건표에 넣었는데 값이 항상 빈 값입니다. 필드 카탈로그 추가(설계 시점)와 통신구조 값 채우기(런타임)는 별개 작업입니다. USEREXIT_PRICING_PREPARE_TKOMK/TKOMP에서 값을 채우지 않으면 조건표 키가 초기값으로 조회되어 레코드를 못 찾습니다.
- Q4. ECC에서 잘 쓰던 KONV 조회 리포트가 S/4HANA에서 깨졌습니다. S/4HANA는 PRCD_ELEMENTS가 원본이며 KBETR 등 일부 필드 길이도 확장되었습니다. 호환 뷰에 의존하기보다 PRCD_ELEMENTS 기준으로 재작성하는 것이 일반적으로 권장됩니다.
- Q5. 조건표를 잘못 만들어 필드 순서를 바꾸고 싶습니다. 레코드가 이미 있는 조건표는 구조 변경이 사실상 불가하므로, 새 번호로 조건표를 새로 만들고 접근순서를 교체한 뒤 레코드를 재생성하는 방식이 안전합니다. 처음부터 "구체적 → 일반적" 키 설계를 검증하고 만드는 습관이 중요합니다.
🚀 이어서 보면 좋은 주제
이번 예제의 구조를 이해했다면 다음 확장이 자연스럽습니다. (1) 조건 배제(Condition Exclusion)로 "여러 할인 중 고객에게 유리한 하나만 적용" 구현, (2) 스케일(수량/금액 단계별 단가)과 그룹 조건, (3) S/4HANA 신규 가격 엔진 관점의 CDS 기반 가격 분석, (4) 리베이트·팩토링 등 사후 정산 조건, (5) 출력결정·자재결정 등 동일한 조건 기법을 쓰는 다른 결정 로직으로의 응용. 특히 조건 배제는 절차·조건유형 설계와 직결되므로 이 글의 5요소 이해가 선행되어야 합니다.
📚 더 읽어보기
- SAP Help Portal — SAP S/4HANA On-Premise 제품 문서 (Sales > Pricing and Conditions)
- SAP Help Portal — SAP ERP(ECC) Sales and Distribution 가격결정 문서
- SAP Help Portal — S/4HANA Cloud 판매 가격 관리 문서 (클라우드 에디션 비교용)
- SAP Community — Sales & Distribution 토픽 (조건 기법 실무 Q&A)
- SAP Learning — SD 가격결정 관련 학습 여정
- SAP Community — ABAP 토픽 (VOFM 루틴·유저이그짓 사례)
댓글 0
아직 댓글이 없습니다.