수익성 분석

계약 수익성 점검 — 수익성 분석, 계약·월별 공헌이익과 계약이익을 유형별 한도에 견주고 적자로 돌아서는 계약까지 한 화면에서

공헌이익 · 공헌이익률 · 계약이익 · 적자 전환 · 한도 미달 · 분류 확인 · 대사 — 소개 영상과 실제 화면 7종으로 보는 계약 단위 수익성 점검

소개 영상1분 38초8개 장면음성 안내 · 자막 포함처음 화면 → 점검 필요 → 상세 → 유형 → 명세 → 대사

도입 포인트 — 이 앱을 사용해야 하는 이유

영업과 재무가 월 마감 뒤에 가장 자주 마주 앉는 질문은 이렇습니다. 이 계약, 팔수록 남는 계약입니까. 매출이 크고 매출총이익이 남아 보여도 운임, 포장, 보증 충당 같은 변동비가 붙고 거기에 설비 상각과 전담 인력 같은 계약 전용 고정비까지 반영하면 적자로 돌아서는 계약이 있습니다. 반대로 매출은 작아도 공헌이익률이 높아 전체 이익을 받쳐 주는 계약도 있습니다. 월 합계 숫자만 보면 이 차이가 서로 상쇄되어 보이지 않습니다.

이 앱은 그 작업을 한 화면에 모읍니다. 계약 명세를 매출 · 변동비 · 계약 고정비 세 구분으로 나누어 계약·월별로 합산하고, 매출에서 변동비를 뺀 공헌이익, 거기서 계약 고정비를 뺀 계약이익, 두 값을 매출로 나눈 공헌이익률과 계약이익률을 계산합니다. 그리고 공헌이익이 음수인지, 공헌이익은 흑자인데 계약이익이 적자로 돌아섰는지, 공헌이익률이 계약 유형별 한도에 못 미치는지 세 가지를 차례로 봅니다. 하나라도 걸리면 ‘점검 필요’로 표시하고, 운임·포장이나 보증 충당처럼 원래 구분과 다르게 전기된 명세는 따로 ‘분류 확인’으로 가려 줍니다. 대상 영역은 관리회계의 수익성 분석입니다. 표준 실행은 SAP 표준 T-code 가 그대로 담당하고, 이 화면은 계약 단위로 한도에 견주는 점검 관점을 더해 확인할 계약·월을 좁힙니다.

한 줄 요약 — 계약별 매출과 이익을 보여 주는 화면은 많습니다. 이 화면의 값은 계약·월마다 공헌이익과 계약이익을 구분해 계산하고, 유형별 한도에 견주어 적자 전환과 한도 미달을 가려 주며, 구분이 어긋난 명세까지 짚어 주는 데 있습니다.

월 합계는 안정적인데 계약 안에서는 적자가 숨어 있다

샘플의 여섯 달 월 합계 공헌이익률은 38.53%에서 41.66% 사이로 크게 흔들리지 않고, 월 합계 계약이익률도 22.69%~26.36%입니다. 그러나 같은 달의 계약을 하나씩 열면 모양이 다릅니다. 프로젝트 수주 B는 3월부터 6월까지 공헌이익률이 39.00%~44.80%로 높은데도 계약 고정비가 커서 네 달 내내 계약이익이 -15.3백만원에서 -21.5백만원 사이의 적자입니다. 합계로 보면 다른 계약의 이익이 이 적자를 덮어 버립니다.

공헌이익이 남아도 계약이익은 다를 수 있다

가격 협상에서는 공헌이익이 중요한 기준이고, 계약 유지 여부를 따질 때는 계약 전용 고정비를 반영한 계약이익이 중요합니다. 두 값을 같은 화면에서 구분해 보면 “변동비까지는 남지만 고정비를 못 덮는 계약”과 “변동비부터 못 덮는 계약”이 갈립니다. 샘플에서 적자 전환은 5건이고, 공헌이익 자체가 음수인 계약·월은 유지보수 계약 D의 5월 한 건(공헌이익률 -12.00%)뿐입니다.

유형마다 기대 마진이 다르므로 한도도 다르다

유지보수·서비스는 변동비가 작아 공헌이익률이 높고, 연간 공급계약은 물량으로 버는 대신 마진이 낮으며, 프로젝트 수주는 그 사이에서 계약 고정비가 큽니다. 한 가지 한도로 모든 계약을 재면 유지보수는 거의 다 통과하고 공급계약은 거의 다 걸립니다. 그래서 한도를 유형별로 두었습니다(샘플: 연간 공급계약 25.00% · 프로젝트 수주 20.00% · 유지보수·서비스 40.00%). 연간 공급 계약 E의 3월 공헌이익률은 14.00%로 한도 25.00%에 못 미쳐 점검 필요가 됩니다.

구분이 어긋난 명세는 이익을 조용히 바꾼다

운임·포장은 변동비로 봐야 하는데 계약 고정비로 들어가면 공헌이익이 과대로 보이고, 보증·하자 충당은 계약 고정비로 봐야 하는데 변동비로 들어가면 반대가 됩니다. 두 경우 모두 합계 계약이익은 그대로여서 합계 대사로는 잡히지 않습니다. 샘플에는 운임·포장이 고정비로 들어간 6건과 보증·하자 충당이 변동비로 들어간 6건, 모두 12건이 있고, 이 화면은 두 구분을 나란히 놓아 이런 명세를 따로 가려 보여 줍니다.

사용 방법

  1. 조회조건을 넣습니다. 회계연도(필수, 4자리)를 확인하고, 필요하면 전기 월 시작·종료, 계약 유형, 계약, 전기일, 점검 결과를 고릅니다. ‘전체’를 고르면 그 조건은 걸리지 않습니다.
  2. 조회합니다. 조건 영역 오른쪽 끝의 조회 버튼을 누르거나 입력 칸에서 Enter 키를 누릅니다. 초기화 버튼은 조건을 처음 값으로 되돌립니다.
  3. 요약을 읽습니다. 위쪽 숫자 칸에서 매출, 공헌이익률, 계약이익률, 점검 필요 계약·월, 분류 확인 필요 명세를 먼저 봅니다.
  4. 탭을 옮깁니다. 계약 판정에서 유형 구성, 명세, 월별 추이, 대사 결과 순서로 넘어갑니다. 탭 이름 위 숫자는 조건에 맞는 건수입니다.
  5. 행을 눌러 상세를 봅니다. 표의 행을 누르면 상세 창이 열려 지표 전체와 같은 계약·월(또는 유형·월)의 명세를 보여 줍니다.
  6. 내려받습니다. CSV 내려받기 버튼은 지금 보고 있는 탭의 조회 결과를 UTF-8 CSV 로 저장합니다.

숫자를 믿을 수 있는가 — 검증 결과

리포트에서 가장 비싼 질문은 “이 숫자 맞아?”입니다. 대사식을 먼저 세우고 샘플 데이터 전수에 돌린 결과입니다.

대사식검사 건수차이 · 예외
매출 − 변동비 = 공헌이익 (계약·월)840
공헌이익 − 계약 고정비 = 계약이익 (계약·월)840
명세 금액(매출 − 변동비 − 고정비) 합계 = 계약 집계 계약이익840
공헌이익 ÷ 매출 × 100 = 공헌이익률, 소수 둘째 자리 반올림840
유형 합계 = 월 합계 = 계약 합계 (매출 · 계약이익)60
전기 구분과 활동 기준 구분이 다른 명세 (의도적 예외)78012 (예외)

요약의 매출 22,204.7백만원, 공헌이익 8,956.2백만원(공헌이익률 40.33%), 계약이익 5,382.6백만원(계약이익률 24.24%), 점검 필요 계약·월 10건(84행 중 11.90%), 분류 확인 필요 명세 12건은 별도 스크립트로 처음부터 다시 계산한 값과 모두 같습니다. 분류 불일치 12건은 합계에는 영향이 없어 대사 차이가 아닌 의도적 예외로 따로 셉니다.

무엇으로 만들었나

자리무엇왜 그렇게 두었나
화면OpenUI5 1.120 · sap_horizon 테마 · 조회조건 + 요약 + 탭 다섯 개SAP 표준 화면과 같은 Horizon 모양이라 현업이 낯설어하지 않습니다
판정·집계계약·월 단위 비율 계산과 유형별 한도 비교, 전기 구분 대조계산이 화면 컨트롤에 흩어지지 않도록 한곳에서 계산합니다
데이터 연결OData V2 모델 한 개를 기본 모델로 선언하고 탭마다 조회 대상 하나에 바인딩운영에서는 서비스 주소만 바꾸면 되고 화면 코드는 건드리지 않습니다
조회 방식조건은 필터로 서버에 보내고 정렬·건수·페이징도 서버가 처리필요한 만큼만 가져오므로 명세가 늘어도 화면이 무거워지지 않습니다
오류 안내서비스 연결 실패와 빈 결과를 구분해 안내 창을 표시연결 문제를 조건에 맞는 데이터가 없는 것으로 오해하지 않게 합니다
테마sap_horizonS/4HANA 사용자의 화면 경험과 맞춥니다
항목내용
기능계약 수익성 점검 — 계약·월별 공헌이익과 계약이익을 유형별 한도에 견주는 점검 화면
대상 영역수익성 분석 (관련 기준서 없음)
표준 T-codeVA43 · VF03 · KE24 · KE30 · FAGLL03 · KSB1
샘플 데이터가상 2026년 1~6월 · 계약 14건(연간 공급계약 6 · 프로젝트 수주 4 · 유지보수·서비스 4) · 명세 780건 · 계약·월 84행

SAP 표준 기능을 그대로 이어받은 부분

매출의 원천은 SAP 표준이 이미 쌓아 둔 청구 문서(VF03)와 판매 계약 조건(VA43), 수익성 라인(KE24)이고, 계정 단위 확인은 FAGLL03, 계약 전용 고정비 원천은 KSB1 이 맡습니다. 이 앱은 그 숫자를 새로 만들지 않고 같은 숫자를 계약·월 단위로 모아 한도에 견주는 자리만 더합니다.

실행 화면

검증용 샘플 데이터로 실제 브라우저에서 찍은 화면 7종입니다. 화면을 누르면 크게 볼 수 있고, 화면 순서는 실제로 쓰는 순서를 따랐습니다.

처음 열었을 때

앱을 열면 올해 값으로 한 번 자동 조회됩니다. 조회조건, 요약, 표가 위에서 아래로 놓입니다.

처음 연 화면 — 조회조건 · 요약 · 계약 판정 표
처음 연 화면 — 조회조건, 요약 숫자, 계약·월별 판정 표가 한 화면에 뜹니다.

앱을 열면 올해 값으로 자동 조회되어 계약 14건 × 6개월, 84행이 한 표에 나옵니다. 위쪽 요약에서 공헌이익률 40.33%와 계약이익률 24.24%를 먼저 읽고, 점검 필요 10건이 어디에 몰려 있는지 표에서 찾아갑니다.

점검 필요만 본 화면 — 점검 결과를 고른 조회
점검 필요만 보기 — 점검 결과를 점검 필요로 고르고 조회하면 확인할 계약·월만 남습니다.

점검 결과를 점검 필요로 고르고 조건 영역 오른쪽 끝의 조회 버튼을 누르면 10행만 남습니다. 입력 칸에서 Enter 키를 눌러도 같습니다. 요약 숫자도 같은 조건으로 함께 바뀝니다.

한 행을 파고든다

월 마감 회의에서는 걸린 계약을 고르고 그 계약의 명세까지 내려갑니다.

행을 눌러 연 계약 상세 창
행을 눌러 상세 보기 — 계약·월 한 행을 누르면 지표 전체와 그 계약의 명세가 열립니다.

표의 행을 누르면 상세 창이 열립니다. 위에는 매출, 변동비, 공헌이익, 계약 고정비, 계약이익과 두 비율, 한도가 나오고 아래에는 그 계약·월을 만든 명세가 나와 비율을 만든 금액까지 따라갈 수 있습니다.

같은 데이터를 다른 묶음으로 본다

유형 구성 · 명세 · 월별 추이는 같은 명세를 유형, 항목, 월로 다시 묶어 보여 줍니다.

유형 구성 탭 — 월별 계약 유형 합계
유형 구성 — 월마다 연간 공급계약, 프로젝트 수주, 유지보수·서비스의 매출과 이익을 나란히 봅니다.

월 합계가 비슷해도 유형별로 보면 모양이 다릅니다. 여섯 달 합계로 공헌이익률은 유지보수·서비스 60.70%, 연간 공급계약 39.50%, 프로젝트 수주 37.63%이고, 계약이익률은 프로젝트 수주가 15.09%로 가장 낮습니다.

명세 탭 — 손익 항목별 금액과 전기 구분
명세 — 손익 항목별 금액과 전기 구분, 활동 기준 구분을 나란히 봅니다.

780건의 명세가 손익 항목, 원천, 전기일, 금액과 함께 나옵니다. 운임·포장이나 보증·하자 충당처럼 활동의 기준 구분과 다르게 전기된 명세 12건은 점검 필요(분류 확인)로 표시됩니다.

월별 추이 탭 — 공헌이익률과 점검 필요 계약 비율
월별 추이 — 여섯 달의 공헌이익률, 계약이익률, 점검 필요 계약 수를 비교합니다.

월 합계 공헌이익률은 38.53%에서 41.66% 사이에서 움직입니다. 점검 필요 계약은 1~2월 0건, 3월 2건, 4월 2건, 5월 4건, 6월 2건으로 3월부터 늘어, 5월에는 월 계약의 28.57%가 걸립니다.

대사 결과 탭 — 합계가 맞는지 확인하는 식
대사 결과 — 정합성 대사 다섯 가지와 의도적 예외 한 가지가 구분되어 나옵니다.

다섯 가지 대사식은 검사 건수와 차이 건수를 보여 주고, 전기 구분이 기준과 다른 명세 12건은 의도적 예외로 따로 셉니다. 대사 차이는 0건입니다.

화면 뒤에서 일어나는 일

계약·월 한 행마다 아래 조건을 위에서 아래로 확인하고, 먼저 걸린 조건 하나를 점검 코드로 표시합니다.

판정 조건결과 상태사용자 조치
공헌이익 = 매출 − 변동비 가 음수 (점검 코드 NEGCM)점검 필요변동비가 매출을 넘어선 계약·월입니다. 명세에서 변동비 항목과 할인·리베이트 금액을 확인합니다.
공헌이익은 흑자이나 계약이익 = 공헌이익 − 계약 고정비 가 음수 (FLIP)점검 필요계약 전용 고정비를 반영하면 적자로 돌아섭니다. 설비 상각·전담 인력·보증 충당 금액이 이 계약에 맞는지 확인합니다.
공헌이익률 = 공헌이익 ÷ 매출 × 100 이 유형별 한도 미만 (LOWCM)점검 필요단가 · 할인 조건 · 원가 구성을 확인하고, 유형 구성 탭에서 같은 유형의 다른 계약과 견줍니다.
세 조건에 모두 해당 없음정상한도 안입니다.
명세의 전기 구분과 활동 기준 구분이 다름 (GRPMIS)점검 필요(분류 확인)변동비로 봐야 할 운임·포장이 고정비로, 고정비로 봐야 할 보증 충당이 변동비로 전기됐는지 확인합니다. 의도적 예외로 따로 집계합니다.

한도(25.00% · 20.00% · 40.00%)는 이 화면의 가상 기준값이며 회사 기준으로 바꿔 씁니다. 점검 필요는 원인을 단정하는 표시가 아니라 확인 대상을 가리는 표시이고, 최종 판단은 회사가 합니다.

산출과 대사의 순서

  1. 명세를 전기 구분별로 모읍니다 — 매출(할인·리베이트는 음수 금액), 변동비, 계약 고정비.
  2. 매출 − 변동비로 계약·월의 공헌이익을, 거기서 계약 고정비를 빼 계약이익을 구합니다.
  3. 공헌이익 ÷ 매출 × 100, 계약이익 ÷ 매출 × 100 으로 두 비율을 구하고 소수 둘째 자리에서 반올림합니다.
  4. 명세 금액 합계가 계약 집계의 계약이익과 같은지, 유형 합계가 월 합계·계약 합계와 같은지 대사합니다.

조회조건

조건필수기본값동작
회계연도필수20264자리 숫자가 아니면 안내 문구를 띄우고 조회하지 않습니다
전기 월 시작 · 종료선택전체둘 다 고르면 그 구간, 하나만 고르면 그 월 이후 또는 이전
계약 유형선택전체전체를 고르면 조건이 걸리지 않습니다
계약선택전체계약 하나를 고릅니다
전기일 시작 · 종료선택비어 있음명세 탭에만 걸립니다
점검 결과선택전체정상 또는 점검 필요

결과 컬럼

컬럼의미산출식
매출계약·월 매출(원), 할인·리베이트 차감 후전기 구분 매출 합계
변동비계약·월 변동비(원)전기 구분 변동비 합계
공헌이익 · 공헌이익률매출에서 변동비를 뺀 금액과 그 비율(%)매출 − 변동비 · 공헌이익 ÷ 매출 × 100
계약 고정비계약에 귀속된 고정비(원)전기 구분 계약 고정비 합계
계약이익 · 계약이익률공헌이익에서 계약 고정비를 뺀 금액과 비율(%)공헌이익 − 계약 고정비 · 계약이익 ÷ 매출 × 100
공헌이익률 한도계약 유형별 기준(%)한도 테이블 값
점검 결과 · 점검 내용정상 또는 점검 필요와 걸린 조건세 조건 비교
분류 확인 필요 명세전기 구분 ≠ 활동 기준 구분인 명세 수명세 대조

파일 구성

앱 폴더/
├─ index.html · readme.html · Component.js · manifest.json   진입점과 서비스 선언
├─ controller/ · view/ · model/ · css/ · i18n/               화면 코드
├─ odata/                                                     서비스 정의와 샘플 데이터
├─ media/                                                     소개 영상과 표지
└─ test/                                                      검증 전용 (앱 본체는 쓰지 않음)

SAP 표준 기능 확장 포인트 — 표준 T-code 와 어떻게 연계되는지

표준 실행은 SAP 표준 T-code 가 담당하고, 이 화면은 조회 · 검증 관점을 더해 확장합니다. 표준이 이미 잘하는 일은 표준에 그대로 두고, 계약 단위로 한도에 견주는 자리만 이어 붙입니다.

표준으로 되는 것과 이 앱이 더하는 것

하고 싶은 일SAP 표준이 앱이 더하는 관점
판매 계약의 기간·단가·할인 조건 확인VA43계약 조건 금액과 이 화면의 계약 단위 매출을 나란히 놓고 대조합니다
청구 문서와 할인·리베이트 라인 확인VF03청구 원천 매출 명세를 계약·월로 모아 한도에 견줍니다
수익성 분석 라인 아이템 보기KE24계약·월 단위로 매출과 변동비를 모아 공헌이익을 계산합니다
수익성 보고서 실행KE30유형 구성 합계를 표준 보고서의 같은 축과 맞춰 봅니다
G/L 계정 라인 확인FAGLL03명세 금액의 원장 계정 라인을 따라가 구분 매핑을 확인합니다
코스트센터 실제 라인 확인KSB1전담 인력·설비 상각 같은 계약 고정비의 원천 라인과 맞춥니다
법정 · 공시 숫자표준 마감 거래이 앱은 만들지 않습니다 — 표준에 그대로 둡니다

T-code 별 연계 지점

T-code이름연계
VA43판매 계약 표시계약 번호별 기간 · 단가 · 할인 조건을 확인합니다. 이 화면의 계약 단위 매출이 계약 조건과 크게 어긋나면 청구 누락이나 할인 적용 오류를 의심할 수 있습니다.
VF03청구 문서 표시명세 중 청구 문서 원천의 매출·할인·리베이트 라인을 문서 단위로 열어 금액을 대조합니다.
KE24수익성 분석 라인 아이템계약·월 매출과 변동비를 표준 수익성 라인과 같은 필드에서 가져오는지 확인합니다.
KE30수익성 분석 보고서 실행유형 구성 합계와 월 합계를 표준 보고서의 같은 축과 매월 맞춰 보는 운영 대사에 씁니다.
FAGLL03G/L 계정 라인 아이템명세 한 줄이 어느 계정에서 왔는지 확인하고, 계정이 어느 구분(매출 · 변동비 · 계약 고정비)에 매핑됐는지 점검합니다.
KSB1코스트센터 실제 라인 아이템계약 전용 고정비(전담 인력 비용, 설비 상각)의 원천입니다. 계약에 귀속시키는 기준이 맞는지 이 화면에서 확인합니다.

분석 지표 정의

지표산식 · 판정 기준대응 기능비고
공헌이익매출 − 변동비, 음수이면 점검 필요계약 판정 · 유형 구성할인·리베이트는 매출에서 차감
공헌이익률공헌이익 ÷ 매출 × 100, 유형별 한도 미만이면 점검 필요계약 판정한도는 가상 기준값
계약이익공헌이익 − 계약 고정비, 음수이면 점검 필요(적자 전환)계약 판정 · 월별 추이고정비는 계약에 귀속된 금액만
계약이익률계약이익 ÷ 매출 × 100계약 판정 · 유형 구성 · 월별 추이참고 지표
점검 필요 계약 비율점검 필요 계약·월 ÷ 계약·월 수 × 100월별 추이월 단위 비교용
분류 확인 필요 명세전기 구분 ≠ 활동 기준 구분명세의도적 예외로 별도 집계

확장 포인트 — 회사마다 달라지는 곳

확장 포인트무엇을 바꾸나화면 코드를 고치나
계정 → 손익 구분 매핑어느 계정을 매출 · 변동비 · 계약 고정비로 볼지아닙니다. 매핑 테이블 값입니다
유형별 한도공헌이익률 하한을 유형이나 사업부별로 얼마로 둘지아닙니다. 한도 테이블 값입니다
계약 단위판매 계약 문서, 프로젝트, 고객 약정 중 무엇을 계약으로 볼지아닙니다. 집계 뷰의 키 선택입니다
공통 비용 배부여러 계약이 함께 쓰는 비용을 계약 고정비에 넣을지아닙니다. 고정비 구분에 배부액을 더하는 일입니다
커스텀 필드계약 담당자나 사업부를 명세에 더해 보려는 경우명세 컬럼 추가가 필요합니다
권한회사코드 · 사업영역 단위로 볼 수 있는 범위아닙니다. 접근 제어 정의입니다

CDS 구성 — 운영 데이터에 붙일 때의 뷰와 테이블

샘플에서는 서비스가 정해진 모양의 데이터를 돌려주지만, 운영에서는 ACDOCA 와 판매 문서, 매핑 테이블에서 같은 모양을 만들어야 합니다. 아래는 그 구성의 스케치이며, 계정 체계와 계약 단위는 회사마다 달라 ‘확인 필요’로 표시한 곳을 도입 때 확정합니다.

뷰 레이어 구성

레이어객체하는 일왜 나누나
기준(매핑)계정 매핑 · 활동 기준 구분 · 유형별 한도계정의 손익 구분, 활동의 기준 구분, 유형별 한도를 담습니다회사마다 다른 기준을 코드가 아니라 값으로 두기 위해서입니다
차원손익 구분 차원구분 코드와 이름을 제공합니다화면의 구분 이름이 한곳에서 나오게 합니다
큐브명세 큐브 · 계약·월 큐브명세 단위 금액과 구분 대조, 계약·월 단위 세 구분 합계를 만듭니다명세 수준과 집계 수준을 나누어 합계 대사를 쉽게 합니다
쿼리(소비)계약 판정 쿼리공헌이익, 계약이익, 두 비율을 계산하고 한도에 견주어 점검 코드를 정합니다판정 규칙을 한곳에 두어 화면이 규칙을 모르게 합니다
권한접근 제어회사코드 단위로 읽을 수 있는 범위를 제한합니다합계 화면으로 다른 조직 숫자가 새는 일을 막습니다
서비스서비스 정의 + 바인딩OData V2 서비스로 게시합니다화면은 서비스 주소만 알면 됩니다

원천 테이블

원천 테이블내용쓰임
VBAK · VBAP판매 문서 헤더 · 품목계약 번호 · 고객 · 계약 유형 · 품목별 계약 조건
VBRK · VBRP청구 문서 헤더 · 품목청구 매출 · 할인·리베이트 라인 · 청구일
ACDOCA유니버설 저널 항목매출 · 변동비 · 고정비 명세 금액 · 전기일
COEP · COBKCO 전표 라인 · 헤더원가 배부 금액 (재료 · 노무 · 상각)
CSKS코스트센터 마스터전담 인력 · 설비 상각 귀속
KNA1고객 마스터고객 이름

① 매핑 테이블 — 계정 · 활동 · 유형 · 한도

계약 단위 손익을 만들려면 먼저 회사의 계정을 매출·변동비·계약 고정비로 나누는 기준과 유형별 한도를 값으로 정해야 합니다. 이 표들이 코드가 아니라 데이터로 있어야 기준이 바뀔 때 화면과 뷰를 고치지 않습니다. 활동 기준 구분 열은 “이 항목은 원래 어느 구분이어야 하는가”를 담아 분류 확인 점검의 비교 대상이 됩니다.

" ─────────────────────────────────────────────────────────
" ① 매핑 테이블
" 역할  : 계정 → 손익 구분, 활동 → 기준 구분, 유형 → 한도
" 이유  : 회사마다 다른 기준을 코드가 아니라 값으로 둔다
" ─────────────────────────────────────────────────────────
@EndUserText.label : '계약 손익 계정 매핑'
define table zctr_accmap {
  key mandt    : mandt not null;
  key ktopl    : ktopl not null;
  key saknr    : saknr not null;     " 계정 (원가요소 포함)
  line_code    : abap.char(5);       " 손익 항목 코드 (R100, V100, F100 ...)
  line_group   : abap.char(1);       " 전기 구분 R 매출 · V 변동비 · F 계약 고정비
}

@EndUserText.label : '활동 기준 구분'
define table zctr_actmap {
  key mandt    : mandt not null;
  key line_code: abap.char(5) not null;
  std_group    : abap.char(1);       " 이 항목이 원래 속해야 하는 구분
}

@EndUserText.label : '유형별 공헌이익률 한도'
define table zctr_limit {
  key mandt    : mandt not null;
  key ctype    : abap.char(1) not null;   " S 공급 · P 프로젝트 · M 유지보수
  cm_limit     : abap.dec(7,2);           " 공헌이익률 하한(%)
}

② 차원 — 계약 유형과 손익 구분

유형과 구분의 이름을 화면 곳곳에 문자열로 흩어 두면 이름이 바뀔 때 놓치는 곳이 생깁니다. 코드와 이름을 한 뷰로 모아 화면이 이름을 이 뷰에서만 가져오게 합니다.

" ─────────────────────────────────────────────────────────
" ② ZI_CtrpGroup — 손익 구분 차원
" 역할  : 구분 코드 R · V · F 의 이름과 정렬 순서를 제공
" 이유  : 화면의 구분 이름이 한곳에서 나오게 한다
" ─────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '계약 손익 구분'
@ObjectModel.resultSet.sizeCategory : #XS
define view entity ZI_CtrpGroup
  as select from dd07t
{
  key cast( substring( domvalue_l, 1, 1 ) as abap.char(1) ) as LineGroup,
      case domvalue_l
        when 'R' then '매출'
        when 'V' then '변동비'
        else '계약 고정비'
      end                                                    as LineGroupName
}
where domname = 'ZCTR_LINE_GROUP'
  and ddlanguage = $session.system_language

③ 큐브 — 명세 단위 (전기 구분과 기준 구분 대조까지)

명세 한 줄마다 전기 구분과 활동 기준 구분을 나란히 두고, 다르면 점검 필요(분류 확인)를 계산해 둡니다. 매출 − 변동비 − 고정비 합계가 구분이 바뀌어도 같다는 점이 대사에서 분류 확인을 대사 차이와 떼어 세는 근거가 됩니다.

" ─────────────────────────────────────────────────────────
" ③ ZI_CtrpItem — 명세 큐브
" 역할  : 판매 문서 연결 계약 번호와 함께 명세 금액, 전기 구분, 기준 구분을 제공
" 이유  : 구분 대조를 명세 수준에서 끝내 집계가 그 결과를 합치기만 하게 한다
" ─────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #CHECK
@EndUserText.label : '계약 손익 명세'
@Analytics.dataCategory : #CUBE
define view entity ZI_CtrpItem
  as select from acdoca as j
    inner join zctr_accmap as a on a.saknr = j.racct
    left outer join zctr_actmap as m on m.line_code = a.line_code
{
  key j.rbukrs                       as CompanyCode,
  key j.gjahr                        as FiscalYear,
  key j.belnr                        as DocNo,
  key j.docln                        as DocLine,
      j.poper                        as FiscalPeriod,
      j.budat                        as PostDate,
      j.kunnr                        as Customer,
      /* 계약 번호는 판매 문서 연결 필드 — 확인 필요 */
      a.line_code                    as LineCode,
      a.line_group                   as LineGroup,
      m.std_group                    as StdGroup,
      j.rhcur                        as Currency,
      @Semantics.amount.currencyCode : 'Currency'
      j.hsl                          as Amount,
      case when a.line_group <> m.std_group then 'CHECK' else 'OK' end as GroupCheck
}

④ 큐브 — 계약·월 단위 집계

세 구분을 한 번의 집계로 가로로 펼칩니다. case 로 구분별 합을 만들고 group by 로 계약·월을 묶으며, 공헌이익과 계약이익은 이 뷰에서 계산하지 않고 소비 뷰에서 만듭니다. 합계의 출처를 한 곳으로 두어야 “명세 합계 = 계약 합계” 대사가 의미를 가집니다.

" ─────────────────────────────────────────────────────────
" ④ ZI_CtrpMonth — 계약·월 큐브
" 역할  : 명세를 계약·월로 묶어 매출, 변동비, 계약 고정비를 제공
" 이유  : 비율 계산의 분자와 분모를 같은 줄에 둔다
" ─────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #CHECK
@EndUserText.label : '계약 손익 계약·월 집계'
@Analytics.dataCategory : #CUBE
define view entity ZI_CtrpMonth
  as select from ZI_CtrpItem as i
{
  key i.FiscalYear,
  key i.FiscalPeriod,
  key i.ContractNo,
      i.Currency,
      @Semantics.amount.currencyCode : 'Currency'
      sum( case i.LineGroup when 'R' then i.Amount else cast( 0 as abap.curr(15,2) ) end ) as Revenue,
      @Semantics.amount.currencyCode : 'Currency'
      sum( case i.LineGroup when 'V' then i.Amount else cast( 0 as abap.curr(15,2) ) end ) as VarCost,
      @Semantics.amount.currencyCode : 'Currency'
      sum( case i.LineGroup when 'F' then i.Amount else cast( 0 as abap.curr(15,2) ) end ) as FixedCost,
      sum( case i.GroupCheck when 'CHECK' then 1 else 0 end )                          as MisCnt,
      count( * )                                                                       as ItemCnt
}
group by i.FiscalYear, i.FiscalPeriod, i.ContractNo, i.Currency

⑤ 쿼리 — 공헌이익 · 계약이익 계산과 점검 판정

이 뷰에서 판정 규칙이 정해집니다. 공헌이익과 계약이익을 계산하고, 비율을 유형별 한도에 견주고, 먼저 걸린 조건을 점검 코드로 만듭니다. 화면은 이 결과만 읽으므로 한도나 규칙이 바뀌어도 화면 코드를 고치지 않습니다. 매출이 0인 계약·월의 비율 처리는 도입 때 정해야 합니다.

" ─────────────────────────────────────────────────────────
" ⑤ ZC_CtrpContractQuery — 소비 쿼리
" 역할  : 공헌이익, 계약이익, 두 비율 계산과 한도 비교
" 이유  : 판정 규칙을 화면이 아니라 뷰에 둔다
" ─────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #CHECK
@EndUserText.label : '계약 수익성 판정'
@Metadata.allowExtensions : true
define view entity ZC_CtrpContractQuery
  as select from ZI_CtrpMonth as p
    left outer join zctr_limit as l on l.ctype = p.CtypeCode
{
  @Consumption.filter : { selectionType : #SINGLE, mandatory : true }
  key p.FiscalYear,
  @Consumption.filter.selectionType : #INTERVAL
  key p.FiscalPeriod,
  @Consumption.filter.selectionType : #SINGLE
  key p.ContractNo,
      p.Revenue, p.VarCost, p.FixedCost,
      ( p.Revenue - p.VarCost )                        as Contribution,
      ( p.Revenue - p.VarCost - p.FixedCost )          as Profit,

      " 비율은 소수 둘째 자리 반올림 — 매출 0 처리는 도입 시 확정 (확인 필요)
      division( cast( ( p.Revenue - p.VarCost ) as abap.dec(15,2) ) * 100,
                cast( p.Revenue as abap.dec(15,2) ), 2 )   as CmRate,
      division( cast( ( p.Revenue - p.VarCost - p.FixedCost ) as abap.dec(15,2) ) * 100,
                cast( p.Revenue as abap.dec(15,2) ), 2 )   as ProfitRate,
      l.cm_limit                                       as CmLimit,

      case
        when ( p.Revenue - p.VarCost ) < 0                                  then 'NEGCM'
        when ( p.Revenue - p.VarCost - p.FixedCost ) < 0                    then 'FLIP'
        when division( cast( ( p.Revenue - p.VarCost ) as abap.dec(15,2) ) * 100,
                       cast( p.Revenue as abap.dec(15,2) ), 2 ) < l.cm_limit then 'LOWCM'
        else ''
      end                                              as CheckCode,
      p.MisCnt
}

⑥ 접근 제어 — 회사코드 단위 권한

권한을 명세 뷰에만 걸면 계약·월 집계나 월별 합계로 다른 조직의 숫자가 새어 나갑니다. 집계 뷰와 소비 쿼리에도 같은 기준을 겁니다.

" ─────────────────────────────────────────────────────────
" ⑥ ZC_CtrpContractQuery 접근 제어
" 역할  : 회사코드 단위로 읽을 수 있는 범위를 제한
" 이유  : 합계 화면으로 다른 조직 숫자가 새는 일을 막는다
" ─────────────────────────────────────────────────────────
@EndUserText.label : '계약 수익성 접근 제어'
@MappingRole : true
define role ZC_CtrpContractQuery {
  grant select on ZC_CtrpContractQuery
    where ( CompanyCode ) = aspect pfcg_auth( F_BKPF_BUK, BUKRS, ACTVT = '03' );
}

⑦ 서비스 정의와 바인딩

마지막 단계는 뷰를 서비스로 게시하는 일입니다. 화면은 게시된 서비스 주소만 알면 되므로, 이 단계가 끝나면 서비스 주소를 화면에 연결하는 것으로 이어 붙이기가 끝납니다. 엔티티셋 이름은 화면이 읽는 이름과 맞춥니다.

" ─────────────────────────────────────────────────────────
" ⑦ ZUI_CtrProfit — 서비스 정의와 바인딩
" 역할  : 다섯 뷰를 OData V2 서비스로 게시
" 이유  : 화면은 서비스 주소만 안다
" ─────────────────────────────────────────────────────────
@EndUserText.label : '계약 수익성 점검 서비스'
define service ZUI_CtrProfit {
  expose ZC_CtrpContractQuery as ContractSet;
  expose ZC_CtrpCtypeQuery    as CtypeSet;
  expose ZI_CtrpItem          as ItemSet;
  expose ZC_CtrpMonthQuery    as MonthSet;
  expose ZC_CtrpReconQuery    as ReconSet;
}

" 서비스 바인딩 : OData V2 - UI  (게시 후 활성화 확인)
" 화면의 manifest 데이터 소스 주소를 이 바인딩 주소로 바꾼다

운영 시점에 해야 할 일

개발보다 정하는 일이 많습니다. 아래 표의 항목은 코딩이 아니라 합의입니다.

해야 할 일무엇을 정하나정하지 않으면누가
계정 → 손익 구분 매핑운임, 포장, 보증 충당, 상각 같은 계정이 매출 · 변동비 · 계약 고정비 중 어디에 속하는지구분 합계가 표준 보고서와 달라 첫 회의에서 막힙니다관리회계 · 영업관리
계약 단위판매 계약 문서, 프로젝트, 고객 약정 중 무엇을 한 계약으로 볼지계약별 이익 숫자가 보는 사람마다 달라집니다관리회계 · 영업관리
유형별 한도공헌이익률 하한을 유형 · 사업부별로 얼마로 둘지점검 필요가 너무 많거나 적어 화면을 신뢰하지 않게 됩니다관리회계 · 영업관리
고정비 귀속 기준어떤 고정비를 계약에 귀속시키고 공통 비용은 배부할지계약이익이 과대 또는 과소로 보여 적자 전환 판정이 흔들립니다관리회계
매출 0 처리매출이 없는 계약·월(휴지, 해지)의 비율을 비워 둘지 0으로 둘지비율 열이 오류를 내거나 의미 없는 값이 나옵니다관리회계
부호 · 환입 처리할인 환입, 반품, 크레딧 노트를 음수 라인으로 둘지 별도로 둘지합계가 의도와 달라집니다관리회계
권한 설계회사코드 · 사업영역 단위로 볼 수 있는 범위합계 화면으로 다른 조직 숫자가 드러납니다보안 · 권한
대사 체계VF03 · KE24 · KE30 · FAGLL03 · KSB1 과 매월 맞출 항목과 허용 차이화면 숫자와 표준 화면 숫자가 어긋났을 때 누가 어떻게 풀지 정해져 있지 않습니다관리회계 · IT
서비스 활성화서비스 게시 후 활성화 확인, 화면의 서비스 주소 교체화면이 연결 안내 창만 띄웁니다IT

위 항목이 합의되면 기술 작업은 CDS 뷰를 만들고 서비스를 게시한 뒤 화면의 서비스 주소를 바꾸는 일입니다. 이 글의 코드는 그 출발점이며, 계정 체계와 계약 단위는 ‘확인 필요’로 남겨 두었습니다.

자주 묻는 질문

도입을 검토하시는 분들이 자주 묻는 내용을 숫자와 산식, 화면과 조작, 분류와 예외, 도입과 운영으로 나누어 모았습니다.

숫자와 산식

공헌이익과 공헌이익률은 어떻게 계산합니까?

공헌이익은 매출에서 변동비를 뺀 금액이고, 공헌이익률은 공헌이익을 매출로 나눠 100을 곱한 뒤 소수 둘째 자리에서 반올림한 값입니다. 할인과 리베이트는 매출에서 음수 금액으로 차감됩니다. 샘플 전체로는 매출 22,204.7백만원에서 변동비를 뺀 공헌이익이 8,956.2백만원이고 공헌이익률은 40.33%입니다. 계약·월 84행 전부에서 이 계산이 표의 값과 맞는지 대사하며 차이는 0건입니다.

계약이익은 공헌이익과 무엇이 다릅니까?

계약이익은 공헌이익에서 계약 고정비까지 뺀 금액입니다. 계약 고정비는 그 계약에 귀속된 설비 상각, 전담 인력 비용, 보증·하자 충당처럼 계약을 따라다니는 비용입니다. 공헌이익이 흑자여도 계약 고정비를 반영하면 적자가 될 수 있고, 이 화면은 그 경우를 ‘적자 전환’으로 따로 가려 보여 줍니다. 샘플 전체의 계약이익은 5,382.6백만원, 계약이익률은 24.24%입니다.

점검 필요 10건은 어떤 조건에서 나옵니까?

계약·월 한 행마다 위에서 아래로 세 조건을 차례로 보고 먼저 걸린 하나를 점검 코드로 표시합니다. 공헌이익이 음수이면 공헌이익 음수, 공헌이익은 흑자인데 계약이익이 음수이면 적자 전환, 공헌이익률이 유형별 한도보다 낮으면 한도 미달입니다. 샘플 84행에서는 공헌이익 음수 1건, 적자 전환 5건, 한도 미달 4건으로 모두 10건이 걸렸고 별도 스크립트의 재계산값과 같습니다.

한도는 어떤 값입니까? 바꿀 수 있습니까?

샘플에서는 연간 공급계약 25.00%, 프로젝트 수주 20.00%, 유지보수·서비스 40.00%를 씁니다. 이 값은 설명을 위한 가상 기준이며 회사의 실제 기준과 무관합니다. 한도는 서비스가 내려주는 데이터의 한 칸이므로 운영에서는 한도 테이블 값을 바꾸면 되고 화면 코드를 고치지 않습니다. 먼저 과거 몇 달 데이터에 돌려 점검 필요 비율이 현업의 체감과 맞는지 본 뒤 확정하시기 바랍니다.

월 합계는 괜찮은데 개별 계약은 점검 필요일 수 있습니까?

그렇습니다. 샘플의 월 합계 공헌이익률은 38.53%~41.66% 안에서 크게 흔들리지 않지만, 3월부터는 프로젝트 수주 B가 공헌이익률 44.80%인데도 계약이익이 -15.5백만원으로 돌아서 있습니다. 합계는 이런 계약을 다른 계약의 이익으로 가려 버리므로 계약·월 단위로 내려가서 봐야 합니다.

점검 필요는 문제가 있다는 뜻입니까?

아닙니다. 한도를 벗어났거나 적자로 돌아섰으니 확인해 보라는 표시이고 원인이나 책임을 단정하지 않습니다. 의도한 가격 정책으로 낮은 마진을 받아들인 계약일 수도 있고, 고정비가 잘못 배부된 계약일 수도 있습니다. 이 화면은 점검 도구이며 최종 판단은 회사와 담당자가 합니다.

화면과 조작

조회조건 중 필수는 무엇입니까?

회계연도 하나입니다. 4자리 숫자가 아니면 안내 문구를 띄우고 조회하지 않습니다. 전기 월 시작·종료, 계약 유형, 계약, 전기일 시작·종료, 점검 결과는 모두 선택이며 ‘전체’를 고르면 그 조건은 서버로 보내지 않습니다.

Enter 키로도 조회됩니까?

됩니다. 조건 입력 칸에서 Enter 키를 누르면 조회 버튼과 같은 동작을 합니다. 조회 버튼은 조건 영역 오른쪽 끝에 있고, 초기화 버튼은 조건을 앱을 처음 열었을 때의 값으로 되돌립니다.

탭 이름 위의 숫자는 무엇입니까?

그 탭에서 지금 조건에 맞는 행 수입니다. 조건을 바꾸면 다섯 탭이 같은 조건으로 함께 다시 읽히므로, 어느 탭에 확인할 행이 몇 개 있는지 탭을 열기 전에 알 수 있습니다.

행을 누르면 무엇이 열립니까?

상세 창이 열립니다. 위쪽에는 그 행의 지표 전체(매출, 변동비, 공헌이익, 계약 고정비, 계약이익, 두 비율, 한도, 점검 내용)가 나오고, 아래쪽에는 같은 계약·월의 명세가 나옵니다. 유형 구성 탭에서는 같은 유형·월의 명세가 열립니다.

CSV 로 내려받으면 무엇이 담깁니까?

지금 보고 있는 탭의 조회 결과가 UTF-8 CSV 로 담깁니다. 조건에 맞는 행 전체가 대상이므로 화면에 보이는 몇 줄이 아니라 조회 결과 전부입니다.

서비스에 연결하지 못하면 어떻게 됩니까?

화면이 빈 표로 조용히 멈추지 않고 서비스 연결 안내 창을 띄웁니다. 메타데이터를 읽지 못한 경우, 요청이 실패한 경우, 조건에 맞는 데이터가 없는 경우를 구분해서 안내하므로 연결 문제를 ‘데이터가 없는 것’으로 오해하지 않습니다.

분류와 예외

전기 구분과 활동 기준 구분이 다르다는 것은 무슨 뜻입니까?

활동 기준 구분은 그 손익 항목이 원래 속해야 하는 구분(예: 운임·포장은 변동비, 보증·하자 충당은 계약 고정비)이고, 전기 구분은 실제로 전표에 들어간 구분입니다. 둘이 다르면 변동비와 고정비가 서로 바뀌어 공헌이익과 계약이익이 의도와 다르게 계산되므로 점검 필요(분류 확인)로 표시합니다. 샘플에는 운임·포장이 고정비로 들어간 6건과 보증·하자 충당이 변동비로 들어간 6건, 모두 12건이 있습니다.

분류 확인 12건은 왜 대사 차이로 세지 않습니까?

합계는 맞고 구분만 다른 건이라서 대사 차이와 성격이 다릅니다. 매출 − 변동비 − 고정비는 구분이 바뀌어도 같으므로 계약이익 합계 대사는 그대로 맞습니다. 분류 확인은 의도적 예외로 따로 세어 ‘대사 차이 0건’이라는 결과가 흐려지지 않게 합니다.

구분이 다르면 어느 쪽이 맞는 것입니까?

화면은 어느 쪽이 맞는지 정하지 않습니다. 활동 마스터의 기준 구분이 오래되었을 수도 있고, 전표 입력 때 잘못 고른 것일 수도 있습니다. 화면이 하는 일은 두 값을 나란히 놓아 확인할 명세를 좁히는 것까지입니다.

금액이 큰 분류 불일치는 어떻게 찾습니까?

명세 탭에서 점검 결과를 ‘점검 필요’로 좁혀 조회하면 분류 확인 명세만 남습니다. 샘플에서는 연간 공급 계약 C의 2월 운임·포장 29.47백만원이 가장 크고, 연간 공급 계약 D의 3월 24.30백만원과 연간 공급 계약 E의 6월 23.64백만원이 뒤를 잇습니다. 금액 열을 눌러 정렬하면 큰 순서로 볼 수 있습니다.

할인과 리베이트는 어디에 들어갑니까?

매출 구분에 음수 금액으로 들어가 매출을 줄입니다. 그래서 할인이 늘어도 변동비는 그대로여서 공헌이익률이 먼저 낮아집니다. 샘플에서 연간 공급 계약 C의 공헌이익률이 4월 20.00%, 5월 18.00%, 6월 19.00%로 한도 25.00%를 밑도는 것이 이런 모양의 사례입니다.

도입과 운영

SAP 표준 화면과 무엇이 다릅니까?

표준 수익성 분석(KE24, KE30)은 매출과 원가를 정해진 축으로 보여 주는 데 강하고, 계약 단위 한도 비교나 변동비·고정비 구분 점검은 보통 엑셀로 따로 만듭니다. 이 화면은 표준 숫자를 대체하지 않고, 같은 숫자를 계약·월 단위로 모아 한도에 견주는 점검 관점만 더합니다.

법정 공시나 결산 숫자로 쓸 수 있습니까?

쓰지 않습니다. 계약 단위 수익성은 회계기준이 정한 표시 항목이 아니라 관리회계 관점의 분석이며, 이 화면은 확인할 계약·월을 좁히는 점검 도구입니다. 법정·공시 숫자는 표준 마감 거래에 그대로 둡니다.

운영 데이터에 붙이려면 무엇을 정해야 합니까?

코딩보다 합의가 먼저입니다. 계약 단위를 판매 문서의 무엇으로 볼지, 전표 계정을 매출·변동비·계약 고정비로 어떻게 나눌지, 유형별 한도를 얼마로 둘지, 공통 비용을 계약에 배부할지 여부를 정해야 합니다. CDS 구성 절의 표에 항목별로 정하지 않으면 생기는 일을 적어 두었습니다.

대용량 데이터에서도 화면이 가볍습니까?

조건은 필터로 서버에 보내고 정렬, 건수, 페이징도 서버가 처리하므로 필요한 만큼만 가져옵니다. 집계는 화면이 아니라 CDS 뷰에서 하므로 명세가 수백만 건으로 늘어도 화면이 읽는 것은 집계된 계약·월 행입니다.

권한은 어떻게 나눕니까?

회사코드나 사업영역 단위의 접근 제어를 집계 뷰에 겁니다. 명세 뷰에만 걸면 계약·월 집계나 월 합계로 다른 조직의 숫자가 새어 나가므로 집계 단계까지 같은 기준을 적용해야 합니다.

공통 비용은 계약에 배부합니까?

이 화면은 계약에 귀속된 고정비만 계약이익에 반영합니다. 여러 계약이 함께 쓰는 공통 비용을 배부할지, 한다면 어떤 기준으로 할지는 회사가 정할 일이라 샘플에는 넣지 않았습니다. 배부 기준을 정하면 계약 고정비 구분에 배부액을 더하는 방식으로 이어 붙일 수 있습니다.

기존 리포트를 없애야 합니까?

아닙니다. 표준 화면과 기존 엑셀은 그대로 두고, 이 화면의 숫자를 표준 숫자와 매월 맞춰 보는 대사 절차를 두는 것을 권합니다. 맞춰 볼 자리는 VA43, VF03, KE24, KE30, FAGLL03, KSB1 입니다.

적용 시기나 의무 범위가 있습니까?

없습니다. 특정 기준서의 시행일에 묶인 화면이 아니고 관련 기준서도 없습니다. 도입 시기는 회사의 월 마감 일정에 맞춰 정하면 되고, 샘플 데이터는 가상의 계약 14건 · 6개월 값입니다.