반품·클레임 손익 점검 — 수익성 분석, 반품으로 생기는 환불·폐기·운임·보상 손실을 품목·월별로 모아 한도에 견주고 점검할 품목을 찾는 월마감 화면
환불에서 순손실까지 · 한도에 견준 점검 필요 · 회수 운임 0원과 전량 폐기 명세 대조 · 행 상세 · 일곱 가지 대사 — 소개 영상과 실제 화면 7종, 그리고 CDS 코드까지
소개 영상1분 31초8개 장면음성 안내·자막처음 화면 → 품목 판정 → 사유별 손실 → 반품 명세 → 상세 → 대사
개발 배경 — 이 앱을 사용해야 하는 이유
월마감이 가까워지면 영업과 품질, 물류가 묻는 것은 “이번 달 반품으로 실제로 얼마를 잃었나” 입니다. 환불만 보면 손실이 커 보이지만 돌아온 물건을 다시 팔아 되돌린 원가가 있고, 반대로 환불 뒤에 회수 운임과 클레임 보상이 따로 붙기도 합니다. 표준 화면은 반품 오더, 대변 메모, 재고 전기, 비용 계정을 각각 잘 보여 주지만, 이 네 가지를 품목·월 단위로 합쳐 “지금 확인해야 할 곳”만 가려 주지는 않습니다.
그래서 현업은 문서를 여러 번 열어 엑셀에 붙이고, 폐기가 유난히 많은 품목이 없는지, 보상이 한 달에 몰리지 않았는지를 눈으로 훑으며 월마감을 보냅니다. 이 앱은 그 훑는 일을 반품 명세 한 건 단위에서 해 두고, 품목·월·사유 순으로 합쳐 올려 한 화면에 놓습니다. 환불·매출 취소액에서 재판매 환입 원가를 빼고 회수 운임과 클레임 보상을 더해 순손실을 만들고, 순매출·반품 원가에 견준 비율을 한도와 비교합니다.
이 화면이 다루는 수익성 분석은 회계기준이 정한 항목이 아니라 관리회계 관점의 분석입니다. 그래서 관련 기준서는 없음(-)으로 적고, 대상 영역을 수익성 분석으로 표기합니다. 점검 필요는 확인할 대상을 가리는 표시이며 최종 판단은 회사가 합니다.
환불액만 보면 실제 손실을 놓친다
여섯 달 동안 환불·매출 취소액은 103.3백만원이지만 재판매로 되돌린 환입 원가가 33.6백만원 있어 순손실은 75.7백만원입니다. 환불에 회수 운임 2.1백만원과 클레임 보상 3.9백만원이 더해진 결과입니다. 환불만 보는 보고서는 손실을 크게 말하고, 환입만 빼 보는 보고서는 운임과 보상을 놓칩니다. 이 앱은 네 가지를 한 식으로 묶어 순손실을 만들고 명세마다 식이 맞는지 검산합니다.
폐기가 많은 품목은 매출 대비 손실로는 안 보인다
1월 정밀 부품은 순손실률이 0.60%로 한도 1.00% 안이지만 폐기율이 69.16%로 한도 55.00%를 넘습니다. 돌아온 물건의 대부분을 다시 팔지 못했다는 뜻인데, 순손실률만 보는 점검은 이 달을 정상으로 넘깁니다. 이 앱은 순손실률, 폐기율, 클레임률 세 가지를 따로 한도에 견주고 걸린 조건을 점검 내용에 모두 적습니다.
운임이 빠지면 손실이 작아 보인다
고객이 직접 반입한 건이나 운임 정산이 늦은 건은 회수 운임이 0원으로 남습니다. 샘플 데이터에는 이런 명세가 7건 있고, 재판매 환입이 0원인 전량 폐기 명세가 4건 있습니다. 한도만 보는 점검은 이런 건을 놓치기 쉬워서, 화면은 두 경우를 의도적 예외로 따로 세어 정합성 대사와 섞이지 않게 했습니다.
합계가 맞는지 묻는 일이 줄어든다
품목별 표와 월별 표, 사유별 표를 따로 만들면 합계가 서로 달라 “어느 숫자가 맞나” 하는 회의가 열립니다. 이 앱은 명세 한 건에서 계산한 값을 품목·월로, 다시 월과 사유로 올리고 일곱 가지 대사식으로 매번 검산합니다. 차이 건수가 요약 카드에 늘 함께 보이므로, 숫자를 믿어도 되는지를 열어 보기 전에 알 수 있습니다.
사용 방법
- 조회조건 입력 — 회계연도(필수, 4자리)를 확인하고, 필요하면 반품 월 시작·종료, 품목, 반품 사유, 반품일 시작·종료, 점검 결과를 고릅니다. 고르지 않은 조건은 걸리지 않습니다.
- 조회 버튼 또는 Enter — 조건 입력칸의 가장 오른쪽 조회 버튼을 누르거나 입력칸에서 Enter 키를 누릅니다. 화면을 열면 기본 조건으로 한 번 자동 조회됩니다.
- 요약 확인 — 순매출, 환불·매출 취소, 순손실, 순손실률, 점검 필요 품목, 확인 필요 명세, 대사 차이 건수를 위쪽 숫자로 봅니다.
- 탭 이동 — 품목 판정 → 사유별 손실 → 반품 명세 → 월별 추이 → 대사 결과 순서로 넘어가며, 탭 이름 위 숫자는 조건에 맞는 건수입니다.
- 행 클릭 상세 — 표의 행을 누르면 상세 창이 열려 지표 전체와 같은 품목·월의 반품 명세를 보여 줍니다.
- CSV 내려받기 — 현재 탭의 조회 결과를 UTF-8 CSV 로 내려받습니다.
숫자를 믿을 수 있는가 — 검증 결과
먼저 대사식을 세우고, 검증용 샘플 데이터 전체에 대해 돌린 결과입니다. 아래 다섯 가지가 화면에 담긴 정합성 대사이고, 의도적 예외 두 가지는 따로 셉니다. 이와 별도로 독립 스크립트가 비율 재계산, 판정 재현, 사유 비중 합계까지 여덟 가지 식을 다시 돌렸고 차이는 모두 0건이었습니다.
| 대사식 | 검사 건수 | 차이 건수 | 최대 차이 |
|---|---|---|---|
| 환불 − 재판매 환입 + 회수 운임 + 클레임 보상 = 순손실 (명세) | 210 | 0 | 0 |
| 재판매 환입 원가 + 폐기 손실 = 반품 원가 (명세) | 210 | 0 | 0 |
| 명세 합계 = 품목·월 집계 (환불 · 순손실) | 30 | 0 | 0 |
| 품목·월 합계 = 월별 집계 (순손실) | 6 | 0 | 0 |
| 사유별 합계 = 월별 순손실 | 6 | 0 | 0 |
의도적 예외 — 회수 운임이 0원인 명세 7건과 재판매 환입이 0원인 전량 폐기 명세 4건은 확인 필요 예시로 넣었으며 대사 차이 건수와 분리해 셉니다. 판정은 30개 품목·월 중 점검 필요 8건이며 별도 스크립트 재계산과 모두 일치했습니다. 화면의 요약 숫자(순매출 12,956.1백만원, 순손실 75.7백만원, 순손실률 0.58%)도 스크립트 결과와 같았습니다.
무엇으로 만들었나
| 자리 | 무엇 | 왜 그렇게 두었나 |
|---|---|---|
| 화면 컨트롤 | OpenUI5 표준 컨트롤(필터 입력, 탭, 표, 상세 창) | 외부 라이브러리 반입 심사 없이 사내망에서 그대로 열리도록 했습니다. |
| 집계·판정 로직 | 서비스 쪽 계산 파일 — 품목·월 집계, 한도 판정, 대사, 순손실률 함수 2종 | 화면은 서비스가 돌려준 값을 그대로 보여 주고, 판정 기준이 화면 코드에 흩어지지 않게 했습니다. |
| OData 구성 | OData V2 서비스 하나. 화면은 매니페스트에 선언한 서비스 주소의 기본 모델로 읽고, 탭마다 해당 엔티티셋에 바인딩합니다. | 조건은 필터 객체로 만들어 조건절로 보내고 정렬·페이징은 모델에 맡겨, 운영 서비스로 바꿔도 화면 코드가 그대로입니다. |
| 오류 처리 | 메타데이터 실패·요청 실패·빈 응답을 구분해 안내하는 오류 처리기 | 서비스가 끊겨도 화면이 빈 채로 멈춘 것처럼 보이지 않게 했습니다. |
| 테마 | sap_horizon | 표준 Fiori 화면과 같은 모양으로 열립니다. |
| 항목 | 내용 |
|---|---|
| 업무 영역 | 관리회계 — 수익성 분석 |
| 관련 기준서·대상 영역 | - (대상 영역: 수익성 분석 — 반품·클레임으로 생기는 순손실 점검) |
| SAP 표준 T-code | KE30 · KE24 · VA03 · VF03 · KSB1 · FAGLL03 |
| 화면 성격 | 조회·점검 (품목·월 판정, 행 클릭 상세, CSV 내려받기) |
| 데이터 연동 | OData V2 |
SAP 표준 기능을 그대로 이어받은 부분
반품 오더와 대변 메모의 금액, 재고 환입과 폐기 전기의 구분, 비용 항목의 구분을 표준 그대로 이어받습니다. 이 화면은 표준 화면의 숫자를 바꾸지 않고, 품목·월 단위로 한도에 견주어 점검하는 관점을 더해 확장합니다.
실행 화면
실제로 돌아가는 화면 7종을 순서대로 싣습니다. 그림을 누르면 크게 볼 수 있고, 화면마다 무엇을 하는 자리인지를 아래에 적었습니다. 숫자는 모두 같은 검증용 샘플 데이터에서 나온 것이라 화면끼리 맞춰 보셔도 됩니다.
처음 열었을 때
처음 화면은 조건, 요약, 판정표 세 단으로 되어 있습니다. 조건을 넣기 전에도 기본 조건으로 한 번 조회되어 빈 화면을 보는 일이 없습니다.

위쪽 일곱 숫자가 순매출 12,956.1백만원, 환불·매출 취소 103.3백만원, 순손실 75.7백만원(순손실률 0.58%)을 먼저 말합니다. 그 옆에서 점검 필요 품목(품목·월) 8건, 확인 필요 명세 26건, 대사 차이 0건이 함께 읽힙니다. 아래 30행 표는 품목·월 한 줄이 하나의 판정 단위이고, 조회 버튼은 조건 입력칸 오른쪽 끝에 있습니다.

점검 결과만 걸어도 8건이 남고, 순손실률·폐기율·클레임률 중 무엇이 한도를 넘었는지가 점검 내용에 문장으로 적혀 있습니다. 요약과 표가 같은 조건에서 나오므로 어느 쪽을 봐도 숫자가 갈라지지 않습니다.
손실이 어느 사유에서 생기는가 — 사유별 손실과 반품 명세
순손실률이 높다는 사실 다음에 오는 질문은 어떤 사유에서, 어떤 건에서 생겼느냐입니다. 사유별 손실에서 비중을 비교하고 반품 명세에서 건별로 내려갑니다.

여섯 달 합계로 보면 운송 파손이 26.1백만원(34.5%), 품질 불량이 25.5백만원(33.7%)으로 둘이 전체 순손실의 3분의 2를 넘고, 오배송 11.9%, 단순 변심 11.7%, 사양 불일치 8.2%가 뒤따릅니다. 귀책 구분(자사·물류·고객)이 함께 있어 누구와 이야기해야 하는지가 곧바로 보입니다.

210건의 반품 명세가 열립니다. 회수 운임이 0원인 7건과 전량 폐기한 4건은 의도적 예외로 넣어 둔 예시이고, 반품일 시작·종료를 넣으면 그 기간의 명세만 남습니다. 환불 대비 순손실률이 95%를 넘는 26건은 점검 필요로 표시됩니다.
흐름과 상세 — 월별 추이와 행 상세
월별 추이로 손실이 몰린 달을 찾고, 행을 눌러 그 달 그 품목의 지표 전체와 명세를 확인합니다.

순손실률은 1월 0.49%에서 3월 0.64%까지 올랐다가 6월 0.59%로 내려옵니다. 점검 필요 품목이 2개인 2월과 3월은 월 단위로도 점검 필요로 표시되고, 나머지 달은 1개씩입니다. 어느 달에 손실이 몰렸는지가 여섯 달 흐름으로 읽힙니다.

표에 다 담지 못한 환불, 반품 원가, 재판매 환입, 폐기 손실, 회수 운임, 클레임 보상과 세 가지 한도가 한 창에 모이고, 그 품목·월의 반품 명세가 아래에 이어집니다. 점검 필요가 아닌 행도 같은 방식으로 열려 정상 행과 견줄 수 있습니다.
숫자를 믿어도 되는가 — 대사 결과
마지막 탭은 화면이 스스로 하는 검산입니다. 합계가 맞는지와 의도적 예외를 구분해 보여 줍니다.

환불 − 재판매 환입 + 회수 운임 + 클레임 보상 = 순손실, 명세 합계 = 품목·월 집계, 사유별 합계 = 월별 순손실 같은 식을 화면이 매번 다시 계산해 차이 0을 보입니다. 의도적 예외 두 가지는 오류와 섞이지 않게 따로 세웁니다.
화면 뒤에서 일어나는 일
조회 버튼을 누르면 화면은 조건을 필터 객체로 만들어 탭마다 해당 엔티티셋에 요청하고, 서비스는 명세에서 품목·월로 합친 값을 돌려줍니다. 한도 판정과 대사도 서비스 쪽 계산 결과이며, 화면은 그 값을 그대로 보여 줍니다.
판정 규칙 — 한도에 견주어 점검 필요를 가린다
품목·월 한 행마다 아래 조건을 차례로 확인하고, 하나라도 걸리면 점검 필요로 표시합니다. 걸린 조건은 점검 내용에 모두 적힙니다.
| 판정 조건 | 결과 상태 | 사용자 조치 |
|---|---|---|
| 순손실률 = 순손실 ÷ 순매출 × 100 이 한도(1.00%)를 넘음 | 점검 필요 | 환불·환입·운임·보상 중 어느 항목이 컸는지 반품 명세로 확인합니다. |
| 폐기율 = 폐기 손실 ÷ 반품 원가 × 100 이 한도(55.00%)를 넘음 | 점검 필요 | 재판매 가능 여부 판정과 폐기 처리 기준이 맞는지 해당 월 명세를 열어 봅니다. |
| 클레임률 = 클레임 보상 ÷ 순매출 × 100 이 한도(0.30%)를 넘음 | 점검 필요 | 보상 건의 사유와 금액 승인 내역을 확인합니다. |
| 명세 한 건의 환불 대비 순손실률이 95%를 넘음 | 점검 필요(명세 확인) | 반품 명세 탭에서 해당 건의 폐기·보상 내역을 확인합니다. |
| 회수 운임이 0원인 명세 | 의도적 예외(별도 집계) | 고객 직접 반입인지 운임 정산 누락인지 확인 필요합니다. |
| 재판매 환입이 0원인 명세(전량 폐기) | 의도적 예외(별도 집계) | 전량 폐기가 타당한 사유인지 확인 필요합니다. |
| 월 안에서 점검 필요 품목이 2개 이상 | 점검 필요(월) | 월별 추이 탭에서 어느 품목이 몰렸는지 확인합니다. |
| 위 조건에 모두 해당 없음 | 정상 | 한도 안입니다. |
한도는 이 화면의 가상 기준값이며 실제 회사의 기준으로 바꿔 쓰면 됩니다. 점검 필요는 원인을 단정하는 표시가 아니라 확인 대상을 가리는 표시이고, 최종 판단은 회사가 합니다.
산출·대사 순서
- 환불 − 재판매 환입 + 회수 운임 + 클레임 보상 = 순손실 (명세)
- 재판매 환입 원가 + 폐기 손실 = 반품 원가 (명세)
- 명세 합계 = 품목·월 집계 (환불 · 순손실)
- 순손실 ÷ 순매출 × 100 = 순손실률 (소수 둘째 자리 반올림), 폐기 손실 ÷ 반품 원가 × 100 = 폐기율, 클레임 보상 ÷ 순매출 × 100 = 클레임률
- 품목·월 합계 = 월 합계, 사유별 합계 = 월별 순손실
조회조건
| 조건 | 필수 | 기본값 | $filter 로 가는 방식 |
|---|---|---|---|
| 회계연도 | 필수 | 2026 | Gjahr eq |
| 반품 월 시작 · 종료 | 선택 | 전체 | Period ge · le (둘 다 있으면 BT) |
| 품목 | 선택 | 전체 | ProdCode eq (전체면 조건 없음) |
| 반품 사유 | 선택 | 전체 | ReasonCode eq (사유별 손실 · 반품 명세) |
| 반품일 시작 · 종료 | 선택 | 비어 있음 | PostDate ge · le (반품 명세) |
| 점검 결과 | 선택 | 전체 | CheckStatus eq |
결과 컬럼
| 컬럼 | 의미 | 산출식 |
|---|---|---|
| 순손실 | 환불액에서 재판매 환입 원가를 빼고 회수 운임과 클레임 보상을 더한 값 | RefundAmt − RecovAmt + FrtAmt + ClaimAmt |
| 반품 원가 | 반품으로 돌아온 물건의 원가. 재판매 환입과 폐기로 나뉜다 | RecovAmt + ScrapAmt |
| 순손실률 | 순매출 대비 순손실 | NetLoss ÷ SalesAmt × 100 |
| 폐기율 | 반품 원가 대비 폐기 손실 | ScrapAmt ÷ RetCost × 100 |
| 클레임률 | 순매출 대비 클레임 보상 | ClaimAmt ÷ SalesAmt × 100 |
| 점검 결과 · 내용 | 한도에 견준 판정과 걸린 조건 | 판정 규칙 표 |
좁은 화면에서 달라지는 것
조회조건은 줄을 바꿔 쌓이고 요약 숫자는 두 칸씩 접힙니다. 표는 화면 안에서 좌우로 넘겨 봅니다. 열이 많은 표라 현장에서는 데스크톱 화면이 더 읽기 편합니다.
파일 구성
index.html · readme.html · Component.js · manifest.json controller/ BaseController.js · Main.controller.js view/ Main.view.xml · DetailDialog.fragment.xml model/ formatter.js · ErrorHandler.js css/ · i18n/ odata/ metadata.xml · service.js · json/ (엔티티셋별 데이터) media/ intro.mp4 · intro_poster.jpg
SAP 표준 기능 확장 포인트
이 앱은 SAP 표준을 대체하지 않습니다. 표준 실행은 SAP 표준 T-code 가 담당하고, 이 화면은 조회·점검 관점을 더해 확장합니다. 표준이 이미 잘하는 일은 표준에 맡기고, 표준이 끊기는 자리만 이어 붙입니다.
표준으로 되는 것과 안 되는 것
| 하고 싶은 일 | 표준으로 충분한 것 | 이 앱이 더하는 관점 |
|---|---|---|
| 품목별 수익성 보고 | KE30 수익성 분석 보고서 | 반품으로 줄어든 몫을 품목·월로 모아 한도에 견주어 보여 줍니다. |
| 개별 항목 확인 | KE24 개별 항목 표시 | 한도를 넘은 품목·월에서 바로 해당 반품 명세로 내려갑니다. |
| 반품 오더 · 대변 메모 확인 | VA03 판매 오더 · VF03 청구 문서 | 반품 명세를 품목·월로 합친 합계와 맞춰 봅니다. |
| 비용 항목 확인 | KSB1 원가 요소별 개별 항목 · FAGLL03 G/L 개별 항목 | 회수 운임과 폐기 손실을 순손실 계산에 연결합니다. |
| 품목별 한도 판정 | 표준에는 없습니다 | 순손실률·폐기율·클레임률 한도를 정해 판정합니다. |
| 합계 대사 | 사람이 표준 결과와 직접 맞춥니다 | 대사식을 화면이 매번 계산합니다. |
T-code 별 연계 지점
| T-code | 이름 | 연계 지점 |
|---|---|---|
| KE30 | 수익성 분석 보고서 실행 | 이 앱이 이어받는 것은 수익성 분석의 손익 구분입니다. 같은 기간·같은 품목의 매출 차감과 손실을 KE30 결과와 맞춰 보는 것이 월마감 대사 지점입니다. 이 앱에서 품목 판정 행을 확인한 뒤 KE30 으로 넘어가 원천 구성을 보고, 표준 화면의 값이 의심스러우면 이 앱의 품목·월 행에서 다시 봅니다. 법정·감사 대응은 표준에 남겨 둡니다. |
| KE24 | 수익성 분석 개별 항목 표시 | 반품 명세 탭의 건수와 금액을 개별 항목 단위로 대조합니다. 건수가 다르면 취소 청구나 기간 경계를 먼저 확인합니다. |
| VA03 | 판매 오더 표시 | 반품 오더의 사유와 수량을 확인합니다. 사유별 손실이 큰 달의 명세에서 오더로 넘어가 사유 입력이 맞는지 봅니다. |
| VF03 | 청구 문서 표시 | 환불·매출 취소의 원천 문서입니다. 반품 명세의 환불액과 대변 메모 금액을 맞춥니다. |
| KSB1 | 원가 요소별 개별 항목 | 회수 운임과 폐기 비용 항목을 확인합니다. 운임이 0원으로 표시된 명세의 정산 여부를 여기서 봅니다. |
| FAGLL03 | G/L 계정 개별 항목 표시 | 재판매 환입, 폐기 손실, 보상 계정 금액이 품목 집계의 합계와 같은지 대조합니다. |
운영 전환 때 “기존 리포트를 없애야 하나” 하는 질문이 따라옵니다. 답은 없애지 않는다입니다. 표준 리포트는 법정·감사 대응과 원천 확인에 그대로 쓰고, 이 화면은 월마감 전에 점검 대상을 가리는 데 씁니다. 두 결과가 같은 기간에서 같은지 맞춰 보는 것이 전환의 첫 단계입니다.
S/4HANA 분석 스택과의 자리
표준 CDS 분석 쿼리나 Fiori 분석 앱, Analysis for Office 는 임의의 축으로 파고드는 탐색에 강합니다. 이 앱은 그 자리를 대신하지 않고, 월마감에서 매번 같은 한도와 같은 대사식으로 확인할 곳을 가려 주는 점검 화면의 자리에 둡니다. 같은 CDS 뷰를 분석 스택과 공유하면 두 화면의 숫자가 갈라지지 않습니다.
확장 포인트 — 운영에서 실제로 손대는 자리
| 자리 | 무엇을 손대나 | 어떻게 |
|---|---|---|
| 사유 매핑 | 반품 사유 코드가 어느 귀책 구분에 속하는지 | 매핑 테이블에 사유·귀책 구분·유효 기간을 둡니다. |
| 한도 | 순손실률·폐기율·클레임률 한도 | 한도 테이블 한 곳에서 품목마다 값을 정합니다. |
| 재판매·폐기 판정 | 검수 결과로 환입과 폐기를 가르는 기준 | 판정 결과 금액을 입력으로 받습니다. 기준 자체는 품질·물류 규정을 따릅니다. |
| 운임·보상 원천 | 회수 운임과 클레임 보상을 반품 명세에 붙이는 방법 | 비용 문서 금액을 반품 항목에 배부합니다. 정산 지연 건은 확인 필요로 둡니다. |
| 확장 필드 | 고객군이나 판매 채널 같은 추가 축 | CDS 뷰에 필드를 더하고 서비스 엔티티에 노출합니다. |
| 권한 | 조회 범위 | 권한 객체의 값으로 집계 단계에서 제한합니다. |
분석 지표 정의표
| 지표 | 산식·판정 기준 | 대응 기능 | 원천 데이터 | 비고 |
|---|---|---|---|---|
| 순손실률 | 순손실 ÷ 순매출 × 100, 한도 초과 시 점검 필요 | 품목 판정 · 월별 추이 | 대변 메모 금액, 재고 환입 | 한도는 가상 기준값 |
| 폐기율 | 폐기 손실 ÷ 반품 원가 × 100, 한도 초과 시 점검 필요 | 품목 판정 · 반품 명세 | 재고 폐기 전기 금액 | 전량 폐기는 별도 집계 |
| 클레임률 | 클레임 보상 ÷ 순매출 × 100, 한도 초과 시 점검 필요 | 품목 판정 | 보상 전표 금액 | 보상 승인 내역 확인 필요 |
| 사유별 비중 | 사유별 순손실 ÷ 월 순손실 × 100 | 사유별 손실 | 반품 오더 사유 | 귀책 구분은 자사·물류·고객 |
| 점검 필요 품목 비율 | 점검 필요 품목 수 ÷ 품목 수 × 100 | 월별 추이 | 품목 판정 결과 | 월 2개 이상이면 점검 필요 |
CDS 구성
화면이 읽는 데이터는 결국 CDS 뷰에서 나옵니다. 아래는 이 화면의 서비스를 S/4HANA 위에서 구성할 때의 뼈대입니다. 코드는 구조를 보이는 스케치이며, 원천 필드와 계정 범위는 회사 설정에 맞춰 확인이 필요한 곳을 주석에 적었습니다.
뷰 레이어 구성
| 레이어 | 뷰·객체 | 하는 일 | 왜 나누나 |
|---|---|---|---|
| 기준(매핑) | ZRETP_REASON · ZRETP_LIMIT | 사유→귀책 구분 매핑과 품목별 한도를 둔다 | 사유 구분과 한도는 정책이라 코드 밖에서 고쳐야 한다 |
| 기본 | ZI_ReturnProfitLine · ZI_ReturnProfitCost | 대변 메모 항목을 반품 명세로 읽고 환입·폐기·운임·보상을 붙인다 | 금액 정의를 한 번만 정해 모든 집계의 바닥으로 쓴다 |
| 큐브 | ZI_ReturnProfitCube | 순손실을 계산하고 품목·월·사유로 집계 가능하게 한다 | 합산 가능한 금액과 비율을 구분한다 |
| 소비(쿼리) | ZC_ReturnProfitQuery | 품목·월로 묶고 한도에 견줘 판정 코드를 만든다 | 화면 코드에 판정 기준이 흩어지지 않게 한다 |
| 권한 | ZC_ReturnProfitQuery(DCL) | 조회 범위를 제한한다 | 집계 단계에서 걸어야 새 나가지 않는다 |
| 서비스 | ZUI_ReturnProfit | 쿼리를 OData V2 로 노출한다 | 주소 한 줄로 개발·운영 전환 |
① 사유 매핑 테이블 — 사유 구분은 코드가 아니라 데이터로
귀책 구분(자사·물류·고객)이 사유별 손실 탭의 읽는 방향을 정합니다. 구분이 바뀔 때마다 화면을 고치지 않도록 유효 기간을 가진 테이블로 둡니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZRETP_REASON (사유 매핑 테이블)
" 역할 : 반품 사유 코드를 귀책 구분(자사·물류·고객)으로 묶는다.
" 이유 : 귀책 구분은 정책이라 코드 밖에서 고쳐야 한다.
" ─────────────────────────────────────────────────────────────
@EndUserText.label : '반품 사유 매핑'
@AbapCatalog.tableCategory : #TRANSPARENT
define table zretp_reason {
key client : abap.clnt not null;
key reason_code : abap.char(3) not null; " 반품 사유 코드
key valid_from : abap.dats not null; " 유효 시작일
valid_to : abap.dats; " 비어 있으면 현재까지
reason_name : abap.char(20);
group_name : abap.char(10); " 자사 · 물류 · 고객
}
② 품목별 한도 테이블 — 한도는 정책이다
세 가지 한도를 품목마다 다르게 둘 수 있습니다. 포장 자재처럼 단가가 낮은 품목과 정밀 부품처럼 높은 품목은 같은 기준으로 견주기 어렵기 때문입니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZRETP_LIMIT (품목별 한도 테이블)
" 역할 : 순손실률 · 폐기율 · 클레임률 한도를 품목마다 둔다.
" 이유 : 한도는 정책이며 바뀔 때 값만 고치면 되어야 한다.
" ─────────────────────────────────────────────────────────────
@EndUserText.label : '반품 손익 한도'
define table zretp_limit {
key client : abap.clnt not null;
key prod_code : abap.char(3) not null;
key valid_from : abap.dats not null;
loss_limit : abap.dec(7,2); " 순손실률 한도(%)
scrap_limit : abap.dec(7,2); " 폐기율 한도(%)
claim_limit : abap.dec(7,2); " 클레임률 한도(%)
}
③ 기본 뷰 — 반품 명세
대변 메모 항목 한 줄이 반품 명세 한 건입니다. 환불·매출 취소액의 정의와 취소 청구의 제외가 모두 여기서 결정되므로 운영에서 가장 먼저 검증해야 하는 뷰입니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZI_ReturnProfitLine (기본 뷰 — 반품 명세)
" 역할 : 대변 메모 항목 한 줄을 반품 명세 한 건으로 읽는다.
" 이유 : 이후 모든 집계의 바닥이므로 금액 정의를 여기서 한 번만 정한다.
" ─────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '반품·클레임 손익 — 반품 명세'
define view entity ZI_ReturnProfitLine
as select from vbrk
inner join vbrp on vbrp.vbeln = vbrk.vbeln
{
key vbrk.vbeln as BillNo,
key vbrp.posnr as BillItem,
vbrk.gjahr as Gjahr,
vbrk.fkdat as PostDate,
vbrp.matnr as MatCode,
vbrp.fkimg as Qty,
/* 환불·매출 취소 = 대변 메모 금액 — 부호와 통화는 회사 설정에 맞춰 확인 필요 */
vbrp.netwr as RefundAmt
/* 재판매 환입 · 폐기 손실 · 회수 운임 · 클레임 보상은 ZI_ReturnProfitCost 에서 붙인다 */
}
where vbrk.fksto = '' /* 취소된 청구 문서는 제외 */
④ 기본 뷰 — 환입·폐기·운임·보상
네 가지 금액은 저널 항목에서 계정 범위로 가려 읽습니다. 계정 번호는 예시이며, 어느 계정에 무엇이 쌓이는지는 회사의 계정 설계를 확인해야 합니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZI_ReturnProfitCost (기본 뷰 — 환입·폐기·운임·보상)
" 역할 : 저널 항목에서 네 가지 금액을 반품 명세에 붙인다.
" 이유 : 계정 범위는 회사마다 달라 한 곳에서만 정의한다.
" ─────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity ZI_ReturnProfitCost
as select from acdoca
{
key rldnr, key rbukrs, key gjahr, key belnr, key docln,
awref as BillNo,
case
when racct between '0000510000' and '0000510999' then 'RECOV' /* 확인 필요: 환입 계정 */
when racct between '0000520000' and '0000520999' then 'SCRAP' /* 확인 필요: 폐기 계정 */
when racct between '0000530000' and '0000530999' then 'FRT' /* 확인 필요: 운임 계정 */
when racct between '0000540000' and '0000540999' then 'CLAIM' /* 확인 필요: 보상 계정 */
end as CostKind,
hsl as Amount
}
where rldnr = '0L' /* 선도 원장 — 원장 선택은 회사 설정 확인 */
⑤ 큐브 — 순손실과 집계
순손실은 명세에서 한 번 계산하고 이후에는 합산만 합니다. 비율은 합산하지 않고 분자·분모를 각각 합한 뒤 쿼리에서 나눕니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZI_ReturnProfitCube (큐브 — 순손실 집계)
" 역할 : 순손실을 계산하고 품목·월·사유로 집계 가능하게 한다.
" 이유 : 합산 가능한 금액과 비율을 구분한다.
" ─────────────────────────────────────────────────────────────
@Analytics.dataCategory: #CUBE
define view entity ZI_ReturnProfitCube
as select from ZI_ReturnProfitLine as l
{
key l.BillNo, key l.BillItem,
l.Gjahr, l.MatCode,
left( l.PostDate, 6 ) as Period,
@DefaultAggregation: #SUM l.RefundAmt,
@DefaultAggregation: #SUM l.RecovAmt,
@DefaultAggregation: #SUM l.ScrapAmt,
@DefaultAggregation: #SUM l.FrtAmt,
@DefaultAggregation: #SUM l.ClaimAmt,
/* 순손실 = 환불 − 재판매 환입 + 회수 운임 + 클레임 보상 */
@DefaultAggregation: #SUM
l.RefundAmt - l.RecovAmt + l.FrtAmt + l.ClaimAmt as NetLoss
}
⑥ 분석 쿼리 — 품목·월 판정
품목·월로 묶어 세 가지 비율을 계산하고 한도에 견줍니다. 판정 코드를 서비스에서 만들기 때문에 화면은 값을 그대로 보여 줄 수 있습니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZC_ReturnProfitQuery (분석 쿼리 — 품목·월 판정)
" 역할 : 품목·월로 묶고 세 가지 한도에 견줘 판정 코드를 만든다.
" 이유 : 판정 기준이 화면 코드에 흩어지지 않게 한다.
" ─────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck: #CHECK
define view entity ZC_ReturnProfitQuery
as select from ZI_ReturnProfitCube as c
inner join zretp_limit as lim on lim.prod_code = c.MatCode
{
key c.Gjahr, key c.Period, key c.MatCode,
sum( c.NetLoss ) as NetLoss,
/* 순손실률 · 폐기율 · 클레임률 — 분모가 0이면 0으로 둔다 */
cast( 100 * sum( c.NetLoss ) / nullif( sum( c.SalesAmt ), 0 ) as abap.dec(7,2) ) as LossRate,
cast( 100 * sum( c.ScrapAmt ) / nullif( sum( c.RetCost ), 0 ) as abap.dec(7,2) ) as ScrapRate,
case when 100 * sum( c.NetLoss ) / nullif( sum( c.SalesAmt ), 0 ) > lim.loss_limit
then 'CHECK' else 'OK' end as LossStatus
/* 폐기율 · 클레임률 판정도 같은 방식으로 이어 붙이고 CheckStatus 로 합친다 */
}
group by c.Gjahr, c.Period, c.MatCode, lim.loss_limit
⑦ 접근 제어와 서비스 정의
조회 범위는 권한 객체의 값으로 집계 단계에서 제한합니다. 화면에서만 숨기면 서비스 주소를 직접 호출하는 경로로 숫자가 새어 나갈 수 있습니다.
" ─────────────────────────────────────────────────────────────
" 객체 : ZC_ReturnProfitQuery(DCL) + ZUI_ReturnProfit(서비스)
" 역할 : 조회 범위를 제한하고 쿼리를 OData V2 로 노출한다.
" 이유 : 권한은 집계 단계에서 걸어야 새 나가지 않는다.
" ─────────────────────────────────────────────────────────────
@EndUserText.label: '반품 손익 권한'
@MappingRole: true
define role ZC_ReturnProfitQuery {
grant select on ZC_ReturnProfitQuery
where ( MatCode ) = aspect pfcg_auth( ZRETPAUTH, PRODCODE, ACTVT = '03' );
}
@EndUserText.label: '반품 손익 서비스'
define service ZUI_ReturnProfit {
expose ZC_ReturnProfitQuery as ProdSet;
expose ZC_ReturnProfitReason as ReasonSet;
expose ZC_ReturnProfitLine as LineSet;
}
운영 시점에 해야 할 일
| 할 일 | 왜 필요한가 | 누가 |
|---|---|---|
| 사유 매핑과 귀책 구분 확정 | 사유별 손실의 읽는 방향이 정해지지 않으면 첫 회의에서 숫자가 어긋납니다. | 품질 · 물류 · 회계팀 |
| 품목별 한도 확정 | 한도가 제각각이면 점검 필요가 의미를 잃습니다. | 영업기획 · 관리회계 |
| 환입·폐기 판정 기준 합의 | 기준이 바뀌면 폐기율이 달라져 월 비교가 안 됩니다. | 품질 · 물류 |
| 운임·보상 계정 범위 확정 | 계정 범위가 틀리면 순손실이 실제와 어긋납니다. | 회계팀 |
| 권한 기준 확정 | 조회 범위를 제한할 기준이 없으면 전체 공개가 됩니다. | 보안 · 관리회계 |
| 표준 결과와 대사 | KE30·KE24 결과와 같은지 맞춰 보는 것이 전환의 첫 단계입니다. | 관리회계 |
운영 데이터로 갈 때
화면의 서비스 주소만 운영 서비스로 바꾸면 되도록 만들었습니다. 첫 달은 표준 화면의 결과와 이 화면의 합계를 나란히 놓고 대사 결과 탭의 차이 건수가 0이 되는지부터 확인하시길 권합니다.
자주 묻는 질문
숫자와 산식, 화면과 조작, 데이터와 표준 연계, 도입과 운영 네 묶음으로 정리했습니다.
숫자와 산식
순손실은 어떻게 계산합니까?
환불·매출 취소액에서 재판매로 되돌린 환입 원가를 빼고, 회수 운임과 클레임 보상을 더한 값입니다. 명세 한 건마다 이 식이 맞는지 210건 전수로 대사하며, 차이가 한 건이라도 있으면 대사 결과 탭과 요약의 대사 차이 건수에 바로 드러납니다.
순손실률과 폐기율은 무엇이 다릅니까?
순손실률은 순손실을 순매출로 나눈 값이라 매출 규모에 견준 손실의 크기를 보여 주고, 폐기율은 폐기 손실을 반품 원가로 나눈 값이라 돌아온 물건 중 다시 팔지 못한 비중을 보여 줍니다. 순손실률이 낮아도 폐기율이 높으면 재판매 판정 기준을 따져 볼 만합니다.
재판매 환입과 폐기 손실은 어떻게 나뉩니까?
반품 원가는 검수 뒤 다시 팔 수 있어 재고로 되돌린 환입 원가와, 다시 팔 수 없어 비용으로 처리한 폐기 손실로 나뉩니다. 두 값을 더하면 반품 원가가 되며, 이 식도 명세 210건 전수로 대사합니다.
한도 값은 어디서 오며 바꿀 수 있습니까?
지금 화면의 한도(순손실률 1.00%, 폐기율 55.00%, 클레임률 0.30%)는 이 화면의 가상 기준값입니다. 실제 적용 때는 회사의 반품 정책과 품목 특성에 맞춰 정하며, 한도는 서비스 데이터의 칸으로 내려오므로 화면 코드를 고치지 않고 값만 바꾸면 됩니다.
점검 필요가 나오면 문제가 있다는 뜻입니까?
아닙니다. 한도를 벗어났으니 확인해 보라는 표시일 뿐 원인이나 책임을 단정하지 않습니다. 일시적인 품질 이슈나 물류 사정일 수도 있습니다. 이 화면은 점검 도구이며 최종 판단은 회사와 담당 부서, 필요하면 감사인이 합니다.
회수 운임이 0원인 명세는 왜 따로 가려냅니까?
운임이 0원이면 순손실이 실제보다 작아 보일 수 있기 때문입니다. 샘플 데이터에는 이런 명세가 7건 있으며, 고객이 직접 반입한 건인지 운임 정산이 빠진 건인지는 화면이 단정하지 않고 확인 필요로 표시해 정산 담당에게 넘기도록 했습니다.
화면과 조작
조회조건은 어떻게 걸립니까?
회계연도만 필수이고 나머지는 고르지 않으면 걸리지 않습니다. 반품 월 시작·종료, 품목, 반품 사유, 반품일 시작·종료, 점검 결과를 조합할 수 있고, 조건은 필터 객체로 만들어 서비스 요청의 조건절로 전달됩니다. 전체를 고르면 그 조건 자체를 보내지 않으므로 코드값을 나열하지 않습니다.
행을 누르면 무엇이 열립니까?
품목·월 한 행을 누르면 상세 창이 열려 지표 전체와 같은 품목·월의 반품 명세를 보여 줍니다. 닫기 버튼으로 돌아오면 조회조건과 탭은 그대로 남아 있어 다음 행을 바로 확인할 수 있습니다.
결과를 엑셀에서 쓸 수 있습니까?
현재 탭의 조회 결과를 UTF-8 CSV 로 내려받을 수 있습니다. 화면의 컬럼 순서와 이름을 따르고, 조건을 좁힌 상태에서 내려받으면 그 범위만 담깁니다.
탭 이름 위의 숫자는 무엇입니까?
현재 조회조건에 맞는 건수입니다. 품목 판정 30, 사유별 손실 30, 반품 명세 210, 월별 추이 6, 대사 결과 7이 기본 조건의 값이고, 조건을 좁히면 같이 줄어듭니다. 어느 탭에 볼 것이 남았는지 열어 보기 전에 알 수 있습니다.
좁은 화면에서도 쓸 수 있습니까?
조회조건이 줄을 바꿔 쌓이고 요약 숫자는 두 칸씩 접히며, 표는 화면 안에서 좌우로 넘겨 봅니다. 열이 많은 표라 현장에서는 데스크톱 화면이 더 읽기 편합니다.
오류가 나면 어떻게 보입니까?
서비스에 연결하지 못하거나 요청이 실패하면 오류 안내 창이 한국어 문구로 뜹니다. 메타데이터 실패, 요청 실패, 빈 응답을 구분해 안내하므로 화면이 빈 채로 멈춘 것처럼 보이지 않습니다.
데이터와 표준 연계
이 화면의 숫자는 어디서 옵니까?
지금은 가상 품목·가상 반품 사유로 만든 검증용 샘플 데이터입니다. 운영에서는 반품 오더와 대변 메모(청구 문서)의 금액, 재고 환입과 폐기 전기, 운임 비용과 보상 계정 금액을 원천으로 합니다. 어느 원천을 어떻게 읽을지는 CDS 구성 절에 코드와 함께 적었습니다.
표준 T-code 의 결과와 어떻게 맞춰 봅니까?
환불·매출 취소는 VA03·VF03 의 문서와, 손익 결과는 KE30·KE24 의 수익성 분석과, 운임과 폐기 비용은 KSB1·FAGLL03 과 맞춰 봅니다. 표준 화면의 숫자는 그대로 두고, 이 화면의 합계가 같은 기간·같은 품목에서 표준 결과와 같은지를 월마감 대사 항목으로 둡니다.
표준 리포트를 없애도 됩니까?
없애지 않는 것을 권합니다. 법정·감사 대응에 쓰는 숫자는 표준 화면이 담당하고, 이 화면은 월마감 전에 한도를 벗어난 품목을 가려내는 조회·점검 관점을 더합니다. 두 결과가 같은지 맞춰 보는 것이 운영 전환의 첫 단계입니다.
적용 시기나 의무 범위가 정해져 있습니까?
없습니다. 반품·클레임 손익 분석은 회계기준이 정한 항목이 아니라 관리회계 관점의 분석입니다. 그래서 관련 기준서는 없음(-)으로 표기하며, 반품 처리 기준과 비용 분류는 회사가 정한 체계를 따릅니다.
반품 사유 구분이 바뀌면 어떻게 합니까?
사유 매핑표에서 사유 코드가 어느 귀책 구분(자사·물류·고객)에 속하는지를 고치면 됩니다. 사유 이름과 코드가 바뀌어도 화면 코드는 건드리지 않습니다.
재판매 가능 여부 판정은 화면이 합니까?
하지 않습니다. 검수 결과로 정해진 환입·폐기 금액을 입력으로 받아 보여 줄 뿐입니다. 어떤 기준으로 재판매 또는 폐기를 정할지는 회사의 품질·물류 기준이며, 그 기준이 바뀌면 폐기율이 달라지므로 도입 때 먼저 합의해야 하는 항목으로 둡니다.
도입과 운영
누가 쓰는 화면입니까?
월마감에서 반품 손실을 확인하는 관리회계 담당자와, 한도를 벗어난 품목의 사유를 되묻는 품질·물류·영업 관리자가 주 사용자입니다. 경영지원 쪽에서는 순손실이 어느 사유에서 커지는지 월별 흐름으로 보는 용도로 씁니다.
도입하면 무엇이 달라집니까?
반품 오더, 청구 문서, 재고 전기, 비용 계정을 따로 열어 엑셀에서 합치던 일이 한 화면의 조회로 줄어듭니다. 한도를 넘은 품목이 먼저 보이므로 훑어보는 시간이 줄고, 대사 결과가 화면에 함께 있어 숫자를 믿어도 되는지 따로 묻는 일이 줄어듭니다.
권한과 보안은 어떻게 둡니까?
남의 사업 범위의 숫자가 보이지 않도록 권한을 집계 단계에서 겁니다. CDS 구성 절의 접근 제어 예시처럼 권한 객체의 값으로 조회 범위를 제한하며, 화면 쪽에서만 숨기지 않는 것이 핵심입니다. 화면은 OpenUI5 표준 컨트롤만 쓰고 외부로 데이터를 보내지 않습니다.
운영 서버에 연결하는 절차와 기간은 어떻게 됩니까?
CDS 뷰를 만들어 서비스를 활성화하고, 화면의 서비스 주소를 운영 서비스로 바꾸면 됩니다. 이 앞에 사유 매핑, 한도, 환입·폐기 금액의 원천을 정하는 합의가 있으며, 실제로 일정을 좌우하는 것은 코딩보다 이 합의입니다. 기간은 회사의 이송 절차와 데이터 정비 수준에 따라 달라 일률로 말하기 어렵습니다.
반품 전표가 수십만 건이면 느려지지 않습니까?
반품 명세를 화면에 그대로 올리지 않고 품목·월 집계를 서버에서 먼저 하도록 구성합니다. 명세 탭은 조회조건(기간·품목)을 필수에 가깝게 두고, 건수는 인라인 건수와 페이징으로 나눠 읽습니다. 운영 규모에서는 집계 뷰를 미리 만들어 두는 방식을 쓰고, 응답 시간 기준은 도입 때 함께 정합니다.
샘플 데이터와 실제 데이터의 형식 차이는 없습니까?
화면은 서비스가 돌려주는 엔티티 형식에만 의존하므로 같은 형식이면 샘플이든 운영이든 똑같이 동작합니다. 날짜는 서비스 표준 날짜 형식으로, 금액과 비율은 십진수 문자열로 주고받습니다. 운영 연결 뒤에는 대사 결과 탭이 표준 화면과의 차이를 가장 먼저 알려 줍니다.
유지보수는 어디에 손이 갑니까?
매달 손이 가는 곳은 한도 값과 사유 매핑 두 곳입니다. 새 반품 사유가 생기면 매핑표에 한 줄을 더하는 것으로 끝나고, 한도는 정책이 바뀔 때 값만 고치면 됩니다. 화면 로직은 서비스 데이터를 그대로 보여 주므로 평소에는 손댈 일이 거의 없습니다.
이 화면이 최종 판단을 대신합니까?
아닙니다. 한도에 견주어 확인 대상을 가려 줄 뿐 반품 정책이나 클레임 보상의 타당성을 평가하지 않습니다. 점검 필요로 표시된 건의 사유를 확인하고 조치를 정하는 것은 회사와 담당자, 필요하면 감사인의 몫입니다.