SAP 수주 잔량 및 미청구 현황 — 출고와 청구, 두 시점의 차이를 한 화면에서
오더수량 대비 얼마나 나갔고, 나간 것 중 얼마를 아직 청구하지 않았는지를 품목 단위로 한 화면에서 확인합니다.
판매오더를 넣었다고 끝이 아닙니다. 오더수량 중 얼마가 아직 나가지 않았는지, 그리고 나간 것 중 얼마를 아직 청구서로 끊지 않았는지는 서로 다른 질문입니다. 잔량은 출고 여부를, 미청구는 청구 여부를 보기 때문에 둘 다 확인하지 않으면 "출고는 다 끝났는데 매출이 안 잡힌" 품목을 놓치기 쉽습니다.
오더 마감 현황이 오더 자체를 닫을지 말지를 보고 매출합산 처리가 여러 청구 전표를 세금계산서 한 장으로 묶는 것과 달리, 이 화면은 출고와 청구라는 두 개의 진행 시점을 수량(잔량)과 금액(미청구)이라는 서로 다른 잣대로 나란히 계산해 품목 단위로 보여줍니다. SAP 표준 데이터 구조를 그대로 이어받아 조회·검증 관점을 더한 OpenUI5 화면으로 확장했습니다. 실제 구동 화면 3종을 함께 공개합니다.
SAP 표준 기능을 그대로 이어받은 부분
- 판매오더 리스트 조회 —
VA05N - 미출고 백오더 리스트 —
V.15 - 청구대상(빌링 듀) 리스트 —
VF04 - 오더·출고·청구 데이터 구조 —
VBAK·VBAP·LIPS·VBRP
| 항목 | 내용 |
|---|---|
| 업무 영역 | 영업(SD) · 수주 잔량 · 청구대상 관리 |
| Namespace | zui5.orderbacklog |
| 셸 구조 | 조회조건 영역(우측 조회) + 오더품목 리스트, 출고·청구 이력 Dialog |
| 화면 수 | 조회 화면 1개 + 상세 다이얼로그 |
| 기준 T-code | VA05N · V.15 · VF04 |
| 성격 | 조회형(Read-Only) — 오더 생성·출고·청구는 표준이 담당 |
| UI 테마 | sap_horizon 단일 적용 |
실제 화면 3종 둘러보기
회사코드·판매조직·기준일자로 조회하면 오더품목별 잔량·미청구 리스트가 뜹니다 → 처리상태로 좁혀 보고 → 품목을 선택해 출고·청구 이력을 확인합니다.
아래는 실제로 앱을 실행해 기능을 눌러 가며 캡처한 화면입니다. 이미지를 클릭하면 원본 크기로 확대됩니다.
조작 방법
- 회사코드를 고르면 그 회사코드에 속한 판매조직 목록만 자동으로 다시 채워집니다.
- 기준일자를 지정합니다. 납기경과일수는 이 날짜를 기준으로 계산됩니다.
- 고객·자재는 코드나 이름 일부만 입력해도 찾아지는 부분일치 검색입니다.
- 오더유형·처리상태로 범위를 좁히고, "미출고 잔량 있는 건만" 옵션으로 완료 건을 뺄 수 있습니다.
- 조회조건 영역 오른쪽 끝의 조회 버튼을 누르거나, 입력 필드에서 Enter 를 눌러도 즉시 결과가 갱신됩니다(단, 한 번이라도 조회한 뒤부터).
- 리스트에서 행을 클릭하거나 상세 버튼을 누르면 그 품목의 출고·청구 이력이 열립니다.
- 리스트와 상세 이력 모두 CSV 다운로드로 내려받을 수 있습니다. UTF-8 BOM 이 붙어 엑셀에서 한글이 깨지지 않습니다.
- 초기화 버튼은 조회조건을 기본값으로 되돌리고 결과를 비웁니다.
잔량·미청구 판정 로직 — 수량과 금액을 함께 추적한다
이 화면의 핵심은 "잔량이 있는가"와 "청구할 몫이 남았는가"를 서로 다른 기준(수량 vs 금액)으로 동시에 판정하는 데 있습니다.
미출고 잔량 = 오더수량 - 출고수량 (0 미만이 되지 않도록 절삭)
잔량율 = 미출고 잔량 / 오더수량 x 100
출고완료 금액 = 오더 순금액 x (출고수량 / 오더수량) (부분출고분을 금액으로 안분, 반올림)
청구완료 금액 = 청구 이력의 (청구수량 x 단가) 합계
미청구 금액 = 출고완료 금액 - 청구완료 금액 (0 미만이 되지 않도록 절삭 → VF04 청구대상 상당)
납기경과일수 = 기준일자 - 납기일 (미출고 잔량이 남아있고 납기일이 지난 경우에만 계산)
처리상태 판정 순서
1) 미출고 잔량 > 0 이고 납기 경과 → 납기경과 잔량
2) 미출고 잔량 > 0 이고 납기 이내 → 미출고 잔량
3) 미출고 잔량 = 0 인데 미청구 금액 > 0 → 청구대상(미청구)
4) 그 외(잔량 0, 미청구 금액 0) → 완료
잔량과 미청구를 분리해서 본 이유
출고는 끝났지만 청구가 늦어지는 품목은 잔량만 보면 "완료"로 보입니다. 반대로 잔량이 남아 있어도 이미 청구된 선수금성 계약이면 미청구 금액은 0일 수 있습니다. 두 지표를 하나로 뭉치면 어느 단계에서 지연이 생겼는지가 가려지므로, 이 화면은 두 값을 별도 컬럼으로 나란히 계산해 보여줍니다.
데이터 처리 흐름 — 오더 · 출고 · 청구를 품목키로 묶어 집계한다
- 오더품목 · 출고이력 · 청구이력 세 데이터를 병렬로 읽습니다.
- 출고·청구 이력을
판매오더+품목키로 미리 인덱싱해, 조회할 때마다 전체를 다시 훑지 않습니다. - 조회조건(회사코드·판매조직·고객·자재·오더유형)으로 오더품목을 먼저 걸러냅니다.
- 걸러진 품목마다 위 판정 로직을 적용해 미출고 잔량·미청구 금액·처리상태·정합성 결과를 계산합니다.
- 처리상태·표시옵션 조건을 다시 적용한 뒤, 납기경과일수 내림차순 → 미청구 금액 내림차순으로 정렬합니다.
- 합계(건수 · 상태별 건수 · 오더 순금액 · 출고완료 금액 · 미출고 잔량 금액 · 미청구 금액)를 별도로 집계해 상단 타이틀과 하단 합계줄에 반영합니다.
- 행을 선택하면 그 품목의 출고·청구 이력만 다시 뽑아 상세 다이얼로그에 채웁니다.
조회조건
| 필드 | 필수 | 설명 |
|---|---|---|
| 회사코드 | 필수 | 선택 시 판매조직 목록이 자동 갱신 |
| 판매조직 | 선택 | 선택된 회사코드에 속한 판매조직만 표시 |
| 기준일자 | 필수 | 납기경과일수 계산 기준일 |
| 고객 | 선택 | 고객코드·고객명 부분일치 |
| 자재 | 선택 | 자재코드·자재명 부분일치 |
| 오더유형 | 선택 | 표준수주 · 직송(3자물류)수주 · 반품수주 |
| 처리상태 | 선택 | 납기경과 잔량 · 미출고 잔량 · 청구대상(미청구) · 완료 |
| 표시옵션 | 선택 | 미출고 잔량이 있는 품목만 표시 |
결과 컬럼
| 컬럼 | 의미 · 표시 |
|---|---|
| 판매오더 · 품목 | 리스트 키 |
| 고객 · 자재 | 코드 + 명칭 |
| 판매조직 · 오더유형 | 명칭 표시 |
| 주문일 · 납기일 | YYYY.MM.DD 형식 |
| 오더수량 · 출고수량 | 단위 포함, 우측정렬 |
| 미출고 잔량 · 잔량율 | 오더수량 - 출고수량, 그 비율(%) |
| 오더 순금액 · 출고완료 금액 | 출고 진행분을 금액으로 안분한 값 |
| 미청구 금액 | 출고는 됐지만 아직 청구서를 발행하지 않은 금액(색상 강조) |
| 납기경과일수 | 잔량이 남아있고 납기가 지난 경우만 표시 |
| 처리상태 | 납기경과 잔량 · 미출고 잔량 · 청구대상(미청구) · 완료 (상태별 색상) |
| 정합성 | 출고≤오더수량, 청구≤출고수량, 순금액=수량x단가 검증 결과 |
SAP 표준 기능 매핑
이 화면은 오더 생성이나 출고·청구 처리를 대체하지 않습니다. 표준 실행은 T-code 가 담당하고, 이 화면은 그 결과를 품목 단위로 모아 잔량과 미청구 금액을 함께 계산해 보여주는 조회·검증 관점을 더해 확장합니다.
| 표준 기능 | T-code | 이 화면이 더하는 부분 |
|---|---|---|
| 판매오더 리스트 조회 | VA05N | 오더수량·출고수량·청구수량을 품목 단위 한 줄로 모아 표시 |
| 미출고 백오더 리스트 | V.15 | 잔량 금액·잔량율·납기경과일수를 함께 계산해 우선순위를 가늠 |
| 청구대상(빌링 듀) 리스트 | VF04 | 출고완료 금액에서 청구완료 금액을 차감한 미청구 금액을 품목별로 바로 제공 |
도입 시 확인이 필요한 부분
미청구 금액을 출고 기준으로 안분할지, 부분 청구를 어떤 순서로 차감할지는 회사의 청구 정책에 따라 달라질 수 있습니다. 반품오더처럼 출고 대상이 아닌 오더유형의 처리 범위도 표준 데이터 구조를 그대로 이어받아 확장하되 도입 조직의 판매 프로세스에 맞춰 조정합니다.
참고 CDS 뷰
운영 서비스로 연결할 때는 오더품목에 출고·청구 집계를 붙인 뷰로 서빙하는 구성을 제안합니다.
@AbapCatalog.sqlViewName: 'ZCSOBACKLOG'
@EndUserText.label: '수주 잔량 및 미청구 현황 (Z)'
define view Z_C_ORDER_BACKLOG
as select from vbap as OrderItem
association [0..1] to vbak as _Header on _Header.vbeln = OrderItem.vbeln
association [0..*] to lips as _Delivery on _Delivery.vgbel = OrderItem.vbeln
and _Delivery.vgpos = OrderItem.posnr
association [0..*] to vbrp as _Billing on _Billing.aubel = OrderItem.vbeln
and _Billing.aupos = OrderItem.posnr
{
key OrderItem.vbeln,
key OrderItem.posnr,
_Header.vkorg,
_Header.kunnr,
OrderItem.matnr,
OrderItem.auart,
_Header.erdat,
OrderItem.edatu,
OrderItem.kwmeng,
OrderItem.netpr,
OrderItem.netwr,
OrderItem.waerk,
sum( _Delivery.lfimg ) as DeliveredQty,
sum( _Billing.fkimg ) as BilledQty,
sum( _Billing.netwr ) as BilledAmt
// 잔량·미청구 금액은 이 집계값을 소비하는 화면/서비스 레이어에서 산출
}
group by
OrderItem.vbeln, OrderItem.posnr, _Header.vkorg, _Header.kunnr, OrderItem.matnr,
OrderItem.auart, _Header.erdat, OrderItem.edatu, OrderItem.kwmeng, OrderItem.netpr,
OrderItem.netwr, OrderItem.waerk
매핑 이해를 돕기 위한 참고용 설계입니다. 실제 도입 시에는 운영 환경의 릴리즈와 청구 정책에 맞춰 조정합니다.
OpenUI5 구성
| 기능 | 사용 컨트롤 |
|---|---|
| 화면 골격 | sap.f.DynamicPage + Fragment 분리(Title/Search/MessageStrip/Table) |
| 조회조건 | sap.m.Select · sap.m.DatePicker · sap.m.Input · sap.m.CheckBox — 우측 끝에 조회·초기화 |
| 이벤트 | 모든 버튼·필드가 onPAI 단일 진입점, fcCode 로 분기 |
| 결과 그리드 | sap.ui.table.Table — 18개 컬럼, 다건 스크롤/고정헤더 대응 |
| 행 강조 | sap.ui.table.RowSettings — 처리상태별 MessageType 강조색 |
| 상세 화면 | sap.m.Dialog + ObjectHeader + sap.m.Table(출고/청구 이력 2종) |
조회조건 영역에 조회 버튼을 둔 이유
하단 고정 바에 조회 버튼을 두면 조건을 여러 개 바꾸는 동안 화면을 오르내려야 합니다. 이 화면은 표준 데이터 구조를 그대로 이어받아 확장하면서, 조회 버튼을 조회조건 영역 오른쪽 끝에 두고 입력 필드에서 Enter 로도 바로 조회되게 해 조건 조정과 실행이 한 자리에서 끝나도록 했습니다.
파일 구성
| 경로 | 역할 |
|---|---|
manifest.json | 앱 디스크립터 — 앱 ID(zui5.orderbacklog) · ko 로케일 · sap_horizon |
view/Main.view.xml | DynamicPage 골격, Title/Search/Table Fragment 결합 |
view/fragments/MainSearch.fragment.xml | 조회조건 + 우측 끝 조회·초기화 버튼 |
view/fragments/MainTable.fragment.xml | sap.ui.table.Table 결과 그리드 |
view/fragments/DetailDialog.fragment.xml | 출고·청구 이력 상세 |
controller/Main.controller.js | 집계·판정 로직, 이벤트 단일 진입점(onPAI) |
model/ModelMock.js | localdata JSON 읽기(Promise) |
model/formatter.js | 금액 · 수량 · 상태 · 날짜 포맷터 |
localdata/orders.json | 오더품목 마스터 432건 |
localdata/deliveries.json | 출고 이력 452건 |
localdata/billings.json | 청구 이력 270건 |
검증 결과
화면 구성에 쓴 데이터는 오더품목 432건 · 출고 452건 · 청구 270건이며, 오더 순금액 합계 2,363,579,900원 중 출고완료 금액 1,581,114,300원, 그 중 미청구 금액 625,461,600원입니다. 납기경과 잔량 162건, 청구대상(미청구) 147건, 완료 115건으로 분류됩니다.
| 검증 항목 | 결과 |
|---|---|
| 품목별 출고수량 ≤ 오더수량 (432건 전수) | 통과 |
| 품목별 청구수량 ≤ 출고수량 (432건 전수) | 통과 |
| 오더 순금액 = 오더수량 x 단가 | 통과 |
| 청구금액 = 청구수량 x 단가 (건별) | 통과 |
| XML · JSON 전체 파싱 | 오류 0건 |
| manifest 참조 · i18n 키 · XML 이벤트 핸들러 누락 | 0건 |
| 조회 버튼 — 조회조건 영역 오른쪽 끝(하단 Bar 아님) | 확인 |
적용 테마 — 부트스트랩 속성 · 런타임 getTheme() 모두 sap_horizon | 확인 |
| Enter 키 조회 — 필터 입력 후 Enter 로 결과 갱신 실동작 확인 | 확인 |
| 화면 렌더링 — 실브라우저 조회 → 상세 실동작 후 캡처 | 3/3 |
고객·자재·금액은 모두 검증용 데이터입니다.
자주 묻는 질문
미출고 잔량과 미청구 금액은 왜 따로 관리하나요?
두 지표가 보는 시점이 다르기 때문입니다. 미출고 잔량은 "아직 물건을 내보내지 않은 수량"을 보고, 미청구 금액은 "물건은 나갔는데 아직 청구서를 끊지 않은 금액"을 봅니다. 출고를 마친 품목이라도 청구가 늦어지면 잔량은 0인데 미청구 금액만 남습니다. 두 값을 하나로 합치면 어느 단계에서 막혀 있는지가 가려지므로 이 화면은 두 지표를 나란히 계산해 보여줍니다.
납기경과일수는 언제부터 계산되나요?
미출고 잔량이 남아 있는 품목에서만, 납기일이 조회 기준일자보다 앞선 경우에만 계산합니다. 이미 전량 출고된 품목은 납기를 지켰든 못 지켰든 더 이상 "경과" 상태로 보지 않고, 미청구 금액이 있으면 별도의 청구대상 상태로 분류합니다.
여러 번 나눠 출고·청구된 품목은 어떻게 처리하나요?
출고와 청구가 여러 건으로 나뉘어도 리스트에는 품목당 한 줄만 남깁니다. 출고수량과 청구수량은 해당 품목에 걸린 모든 건을 합산한 값이며, 상세 다이얼로그를 열면 언제 몇 개씩 나갔고 언제 얼마씩 청구했는지 건별 이력을 그대로 펼쳐 확인할 수 있습니다.
SAP 표준 기능과 어떻게 이어지나요?
판매오더 리스트는 VA05N, 미출고 백오더는 V.15, 청구대상 리스트는 VF04가 각각 담당합니다. 이 화면은 세 화면의 데이터를 품목 단위로 모아 잔량과 미청구 금액을 함께 계산해 보여주는 조회·검증 관점의 확장이며, 오더 생성이나 출고·청구 처리 자체는 그대로 표준 트랜잭션이 수행합니다.