수입 솔루션 · 구매(MM) 수입 원가

SAP 수입 부대비용 배부 및 수입 원가 확정 점검 — 운임·보험·관세를 품목에 나누고 장부와 맞춰 보는 화면

선하증권(B/L) 단위 원가 확정 · 중량·가액·수량 기준 품목 배부 · 단수 조정 · 환급 가능 수입 부가가치세 제외 · 장부 취득원가 대사 · 선하증권 상세 창 — 소개 영상과 실제 화면 6종, 그리고 CDS 코드까지

소개 영상1분 44초8개 장면음성 안내·자막조회조건 → B/L 원가 확정 → 품목별 배부 → 부대비용 명세 → 상세 → 대사

개발 배경 — 이 앱을 사용해야 하는 이유

수입 담당자의 월말은 같은 질문으로 시작합니다. 이번 달 들어온 B/L 의 수입 원가는 얼마로 확정됐나, 운임·보험·관세·통관 비용은 품목마다 얼마씩 얹혔나, 그 숫자가 장부 취득원가와 맞나. 지금은 이 세 답이 구매오더 화면(ME23N)과 입고 문서(MIGO · MB51), 송장 검증(MIRO), 그리고 포워더와 관세사가 보낸 청구서 엑셀에 흩어져 있습니다. 화면마다 보는 단위가 다릅니다. 구매오더는 품목, 입고는 자재 문서, 송장은 송장 한 장이고, 비용을 청구하는 쪽은 B/L 한 건을 단위로 움직입니다.

이 앱은 그 사이를 이어 붙입니다. 선하증권 한 건을 기준으로 외화 물품 대가를 원화로 옮기고, 그 B/L 에 모인 부대비용을 비용마다 정해진 기준(중량·가액·수량)으로 품목에 나눈 뒤, 수입 원가를 다시 구해 장부 취득원가와 나란히 놓습니다. 새로 계산하는 값은 모두 SAP 표준 데이터 구조(구매오더·자재 문서·송장 검증·회계 전표)에서 읽은 값을 그대로 이어받습니다. 표준 실행은 SAP 표준 T-code 가 담당하고, 이 화면은 조회·검증 관점을 더해 확장합니다.

관련 기준은 IAS 2 재고자산(K-IFRS 제1002호)입니다. 매입원가에 매입가격·수입관세와 취득에 직접 관련된 운송·취급 비용을 포함하고 환급 가능한 세금은 제외한다는 취지의 요구를 화면에서 점검할 수 있도록 풀었습니다. 문단번호와 시행일은 원문 확인 후 정하며, 이 글은 기준서 해석을 대신하지 않습니다.

한 줄 요약 — 원가 계산식 자체는 어렵지 않습니다. 어려운 것은 B/L 마다 비용이 다른 때에 도착하고, 비용마다 나누는 기준이 다르고, 나눈 합이 청구액과 1원도 어긋나면 안 된다는 점입니다. 이 앱은 그 세 가지를 한 화면에서 검산합니다.

B/L 한 건의 원가는 송장이 다 모여야 끝난다

배가 도착하고 입고가 되어도 원가는 바로 확정되지 않습니다. 해상운임은 포워더가, 통관수수료는 관세사가, 하역·보관료는 터미널이 따로 청구하고 각자 다른 날 도착합니다. 그동안 구매오더에는 예정 부대비용이 들어 있고, 청구가 도착할 때마다 실제 부대비용이 송장 검증으로 쌓입니다. 마감 시점에는 일부는 확정, 일부는 예정으로 남은 B/L 이 섞여 있습니다.

이 앱은 B/L 한 건마다 예정 합계와 실제 합계, 차이와 차이율을 한 줄에 놓습니다. 같은 입고 연월의 B/L 이 몇 건이고 그중 어디가 예정 대비 허용 범위(샘플은 ±10%, 가정값)를 넘었는지 위쪽 요약에서 먼저 보입니다. 예를 들어 이 글의 샘플 데이터 10월분 5건에서는 실제 부대비용이 52,787,510원이고, 점검이 필요한 B/L 은 4건입니다.

품목에 나누는 기준이 비용마다 다르다

수입 원가는 품목 단위로 쌓입니다. 한 B/L 에 냉연강판 코일, 부품, 포장재가 함께 실려 오면 운임 4,120,000원을 어떻게 나눌지가 곧 품목 원가가 됩니다. 이 앱의 기본 기준은 세 가지입니다. 운임과 하역·보관은 중량으로, 보험료와 관세는 가액으로, 통관수수료는 수량으로 나눕니다. 회사마다 기준이 다를 수 있으므로 기준은 매핑으로 두고 코드에 박지 않았습니다(CDS 절 참고).

나누다 보면 원 단위 이하의 단수가 남습니다. 이 앱은 단수를 마지막 품목에 모아 조정하고, 그 조정액을 컬럼으로 따로 보여 줍니다. 합계는 늘 청구액과 같고, 조정이 어디서 일어났는지도 숨기지 않습니다.

환급되는 수입 부가가치세가 원가에 섞이면 장부가 어긋난다

수입 시점에 내는 부가가치세는 환급 가능한 경우 재고 원가에 넣지 않습니다. 그런데 실무에서는 통관 비용 묶음에 함께 실려 와 취득원가로 들어가 버리는 일이 생깁니다. 이 앱은 부대비용 명세에서 원가 포함 여부를 비용마다 표시하고, 환급 가능 수입 부가가치세는 수입 원가 계산에서 제외합니다. 장부 취득원가가 산출한 수입 원가보다 부가가치세 몫만큼 크게 잡혀 있으면 점검 필요로 띄웁니다. 포함 여부의 최종 판단은 회사와 세무 대리인이 합니다.

예정과 실제의 차이는 마감 때 한꺼번에 드러난다

예정 부대비용이 실제와 크게 다르면 입고 때 잡힌 단가와 마감 때의 원가가 어긋납니다. 하나씩 열어 비교하면 B/L 이 많을수록 시간이 들고, 엑셀로 옮기면 어느 숫자가 최신인지 헷갈립니다. 이 앱은 예정과 실제의 차이를 B/L 행마다 금액과 비율로 나란히 두고, 허용 범위를 넘은 B/L 을 점검 필요로 표시해 먼저 열어 볼 순서를 정해 줍니다.

그래서 무엇을 보려는 앱인가

세 가지입니다. 부대비용이 품목에 빠짐없이 나뉘었는지, 산출한 수입 원가가 장부 취득원가와 맞는지, 그리고 예정과 실제의 차이가 큰 B/L 중 어느 것을 먼저 열어야 하는지입니다. 이 앱은 점검 도구입니다. 원가를 확정하거나 전표를 만들지 않으며, 결과를 근거로 한 판단은 회사와 감사인이, 관세와 부가가치세 신고는 회사와 세무 대리인·관세사가 합니다.

사용 방법

  1. 조회 조건에서 입고 연월(필수)을 확인합니다. 통화·점검 상태·B/L 일자(부터·까지)는 선택이며, 비워 두면 조건에서 빠집니다.
  2. 조회 버튼을 누릅니다. 입력 칸에서 Enter 키를 눌러도 같은 조회가 실행되고, 초기화 버튼은 그 옆에 있습니다.
  3. 위쪽 요약(B/L 건수 · 물품 대가 · 실제 부대비용 · 수입 원가 · 점검 필요 · 장부 대비 차이)을 확인합니다.
  4. 탭을 차례로 봅니다 — B/L 원가 확정 → 품목별 배부 → 부대비용 명세 → 대사 결과.
  5. 궁금한 행을 누르면 선하증권 상세 창이 열려 품목과 부대비용을 함께 봅니다.
  6. 하단 CSV 내려받기로 B/L 원가 확정·품목별 배부·부대비용 명세 탭의 내용을 UTF-8 CSV 로 저장합니다.

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

원가 점검에서 가장 비싼 질문은 “이 숫자 맞아?” 입니다. 그래서 만드는 쪽에서 먼저 대사식을 세워 두고 샘플 데이터 전수로 돌렸습니다.

대사식검사 건수차이 건수최대 차이(원)
배부 전 부대비용 = 품목별 배부액 합계700
예정 + 차이 = 실제 부대비용700
수입 원가 = 물품 대가 + 배부 부대비용700
품목 수입 원가 합계 = B/L 수입 원가700
장부 취득원가와 산출 수입 원가 대사721,971,530
USD 외화 금액 × 환율 = 원화 물품 대가200
EUR 외화 금액 × 환율 = 원화 물품 대가200
JPY 외화 금액 × 환율 = 원화 물품 대가100
CNY 외화 금액 × 환율 = 원화 물품 대가200

장부 대사의 차이 2건은 의도적 예외입니다. 점검 화면을 시연하려고 샘플에 장부 차이 1건, 예정 대비 차이 1건, 부가가치세 포함 1건, 중량 누락 1건(품목 기준)을 일부러 넣었고, 이 가운데 장부와 맞지 않는 두 B/L(장부 차이 1건, 부가가치세 포함 1건)이 위 표의 2건입니다. 나머지 대사식은 모두 차이 0 입니다. 화면 쪽은 별도로 브라우저 자동화를 돌려 탭 이동, 날짜 조건 걸러짐, 상세 창 열림과 닫힘을 다시 확인했습니다.

무엇으로 만들었나

자리무엇왜 그렇게 두었나
화면 컨트롤OpenUI5 표준 컨트롤(sap.ui.table.Table · sap.m · sap.ui.layout)외부 차트·그리드 라이브러리 없이 표준 컨트롤만 써서 사내 보안 심사 부담을 줄입니다.
집계·판정 로직배부 · 단수 조정 · 판정(L01~L04) · 대사 계산을 서비스 로직 한 파일에 모음화면이 계산하지 않고 서비스가 계산한 값만 보여 주어 화면과 숫자가 갈라지지 않습니다.
OData 서비스 구성OData V2 서비스를 앱 설정(manifest)에 선언하고 이름 없는 기본 모델에 연결. B/L · 품목 · 부대비용 · 대사 네 묶음을 탭마다 바인딩조건은 표준 필터로, 정렬은 표준 정렬로 보냅니다. “전체”는 값을 보내지 않고 조건에서 뺍니다.
오류 처리서비스 정보 실패와 요청 실패를 구분해 메시지로 표시연결 문제와 조건 문제를 사용자가 구분해 조치할 수 있게 합니다.
테마sap_horizonS/4HANA Fiori 와 같은 시각 체계로 보입니다.
항목내용
솔루션수입 솔루션
업무 영역구매(MM) · 수입 원가
관련 기준서·대상 영역IAS 2 재고자산(K-IFRS 제1002호) · 수입 원가 확정
SAP 표준 T-codeME23N · MIGO · MIRO · MB51 · MR11
화면 성격조회·점검 (배부·집계·대사)
데이터 연동OData V2
SAP 표준 기능을 그대로 이어받은 부분 — 구매오더의 물품 대가와 예정 조건, 자재 문서의 입고 수량과 취득원가, 송장 검증의 부대비용 라인, 회계 전표의 장부 금액은 모두 표준 데이터 구조의 값을 그대로 읽습니다. 이 화면은 새 원장이나 새 마스터를 만들지 않고, 같은 값을 B/L 과 품목 기준으로 다시 묶어 보여 주는 조회·점검 관점만 더합니다.

실행 화면

실제로 돌아가는 화면 6종을 사용 순서대로 싣습니다. 그림을 누르면 크게 볼 수 있고, 화면마다 무엇을 보는 자리이고 숫자를 어떻게 읽는지를 아래에 적었습니다. 숫자는 모두 같은 샘플 자료에서 나온 것이라 화면끼리 맞춰 보셔도 됩니다.

처음 열었을 때

입고 연월이 기본으로 들어간 상태에서 조회조건, 요약 지표, 첫 번째 탭이 한 화면에 세로로 쌓입니다. 무엇을 고르면 무엇이 채워지는지를 한눈에 봅니다.

처음 연 화면 — 조회조건·요약·첫 탭
처음 연 화면 — 조회조건·요약·첫 탭 — 조회조건 아래로 요약 지표 여섯 칸과 B/L 원가 확정 탭이 이어집니다. 입고 연월은 기본값 202610 이 들어가 있고, 조회를 누르면 같은 연월의 B/L 이 표에 채워집니다.

위쪽 요약은 B/L 5건, 물품 대가 375,213,514원, 실제 부대비용 52,787,510원, 수입 원가 428,001,024원, 점검 필요 4건, 장부 대비 차이 +2,156,530원입니다. 수입 원가는 물품 대가와 실제 부대비용의 합이라 두 숫자를 더하면 맞습니다. 표는 B/L 일자가 최근인 것부터 정렬되며, 맨 오른쪽 상태 칸이 점검 필요인 행부터 열어 보면 됩니다.

점검이 필요한 B/L 만 골라 보기

B/L 원가 확정 탭은 선하증권 한 건이 한 줄입니다. 외화 금액과 가정 환율, 원화 물품 대가, 예정과 실제 부대비용, 차이, 수입 원가, 장부와의 차이가 같은 줄에 놓입니다. 점검 상태를 ‘점검 필요’ 로 두고 조회하면 먼저 열어 볼 B/L 만 남습니다.

점검 필요 B/L 만 조회 — 예정·실제 부대비용과 수입 원가
점검 필요 B/L 만 조회 — 예정·실제 부대비용과 수입 원가 — 점검 상태 조건을 걸고 조회한 모습입니다. 요약 지표도 조건에 맞는 B/L 4건 기준으로 다시 계산됩니다.

네 건의 이유가 서로 다릅니다. EUR 건은 실제 부대비용이 예정보다 13.29% 적어 허용 범위(±10%, 가정값)를 벗어났고, JPY 건은 장부 취득원가가 산출 수입 원가보다 1,971,530원 큽니다. USD 건은 장부와 185,000원 차이가 나고, CNY 건은 품목 중량이 비어 배부 기준이 맞지 않습니다. 서로 다른 통화의 외화 금액은 더하지 않으며, 합계는 원화 열에서만 냅니다.

품목에 나누기 — 배부 기준

품목별 배부 탭은 B/L 안의 품목을 한 줄씩 펼칩니다. 운임·보험료·관세·통관수수료·하역·보관이 각각 품목에 얼마씩 얹혔는지가 열로 나뉘고, 오른쪽 끝에서 수입 원가와 단위 원가가 나옵니다.

품목별 배부 — 운임·보험·관세·통관·하역 배부와 수입 원가
품목별 배부 — 운임·보험·관세·통관·하역 배부와 수입 원가 — 비용 다섯 종류가 열로 나뉘어 있어 어느 비용이 품목 원가를 얼마나 올렸는지 바로 읽힙니다.

예를 들어 BL-0001 의 냉연강판 코일(40 EA, 9,600 kg)은 물품 대가 45,441,120원에 배부액 6,324,838원이 붙어 수입 원가 51,765,958원, 단위 원가 약 1,294,149원입니다. 운임은 중량 비율로, 관세는 가액 비율로 나눈 값이라 같은 B/L 의 다른 품목과 비율이 다릅니다. 중량이 비어 있는 품목은 배부가 어긋나므로 점검 필요로 나옵니다.

부대비용 명세 — 무엇이 원가에 들어가나

부대비용 명세 탭은 B/L 에 모인 비용을 한 줄씩 보여 줍니다. 비용마다 배부 기준(중량·가액·수량)과 원가 포함 여부가 붙어 있고, 예정 금액과 실제 금액, 그 차이가 나란히 있습니다.

부대비용 명세 — 배부 기준과 원가 포함 여부
부대비용 명세 — 배부 기준과 원가 포함 여부 — 비용 한 줄마다 어떤 기준으로 나뉘고 원가에 들어가는지가 보입니다. 환급 가능한 수입 부가가치세는 원가에 포함하지 않는 줄로 따로 나옵니다.

이 탭은 배부 결과가 왜 그렇게 나왔는지를 거슬러 올라가는 자리입니다. 품목별 배부의 숫자가 이상하면 여기서 해당 비용의 기준과 포함 여부부터 확인합니다. 수입 부가가치세 줄은 금액이 커도 수입 원가 합계에는 들어가지 않습니다.

B/L 에서 품목·비용까지 — 상세 창

표의 행을 누르면 선하증권 상세 창이 열립니다. 탭을 오가지 않고 한 B/L 의 품목 배부와 부대비용 명세를 한 창에서 봅니다.

선하증권 상세 — 품목별 배부와 부대비용 명세
선하증권 상세 — 품목별 배부와 부대비용 명세 — B/L 요약 아래로 품목별 배부와 부대비용 명세가 이어집니다. 점검 필요로 나온 이유가 같은 창 안에서 확인됩니다.

점검 필요 B/L 을 열었을 때 가장 먼저 보는 화면입니다. 이 예(BL-0005)는 장부 취득원가 194,898,638원이 산출 수입 원가 194,713,638원보다 185,000원 크다는 사유가 위쪽에 적혀 있고, 아래 두 표에서 그 사유가 어느 품목이나 어느 비용에서 왔는지 찾습니다. 닫기 버튼이나 바깥 클릭으로 창을 닫으면 원래 탭의 위치 그대로 돌아옵니다.

대사 — 합계가 맞는지 스스로 점검

대사 결과 탭은 화면이 스스로 하는 검산입니다. 배부 합계와 청구액, 예정과 실제, 산출 원가와 장부를 항목별로 견주고 검사 건수·차이 건수·최대 차이를 적습니다.

대사 결과 — 정합성·장부·통화별 대사
대사 결과 — 정합성·장부·통화별 대사 — 구분은 정합성, 장부, 통화별로 나뉩니다. 차이 건수가 0 이 아닌 줄만 따로 눈에 띕니다.

대사 결과는 입고 연월과 관계없이 샘플의 B/L 7건 전체를 대상으로 합니다. 정합성 대사는 모두 차이 0 이어야 정상이고, 장부 대사의 차이 2건은 샘플에 일부러 넣은 예외입니다. 통화별 대사는 통화마다 따로 계산하며 서로 다른 통화를 더하지 않습니다. 운영 데이터에서 이 탭에 차이 건수가 보이면 그 줄의 B/L 부터 상세 창으로 확인합니다.

화면 뒤에서 일어나는 일

여기부터는 화면이 어떤 규칙으로 그렇게 움직이는지를 적었습니다. 도입 검토에서 “그래서 이건 어떻게 계산되느냐” 로 자주 되돌아오는 대목입니다.

원가가 만들어지는 여섯 단계

순서산출·대사식SAP 데이터 지점
1원화 물품 대가 = 외화 금액 × 가정 환율구매오더(EKKO · EKPO) · 입고(MSEG)
2품목별 배부액 = 부대비용 × 품목 기준 값 ÷ 기준 값 합계 (단수는 마지막 품목에서 조정, 조정액 별도 표시)송장 검증(RBKP · RSEG) 부대비용 라인
3수입 원가 = 물품 대가 + 배부 부대비용 (환급 가능 수입 부가가치세 제외)자재 문서(MSEG) 취득원가
4예정 부대비용 + 차이 = 실제 부대비용구매오더 조건(EKPO) 예정 금액
5품목 수입 원가 합계 = B/L 수입 원가, 배부 전 부대비용 합계 = 품목 배부액 합계—
6장부 취득원가 − 산출 수입 원가 = 장부 대비 차이전표(BKPF · BSEG)

진행 흐름은 구매오더 → 신용장 개설 → 선적·선하증권 → 통관 → 입고 → 대금 결제입니다. 이 화면은 선적 이후 부대비용이 확정되는 구간을 다룹니다.

배부 기준과 단수 조정

비용기준나누는 방법원가 포함
해상운임중량(W)품목 중량 ÷ B/L 중량 합계포함
보험료가액(V)품목 물품 대가 ÷ B/L 물품 대가 합계포함
관세가액(V)품목 물품 대가 ÷ B/L 물품 대가 합계포함
통관수수료수량(Q)품목 수량 ÷ B/L 수량 합계포함
하역·보관중량(W)품목 중량 ÷ B/L 중량 합계포함
수입 부가가치세가액(V)원가 계산에서 제외 (환급 가능분)제외

각 비용은 먼저 원 단위로 반올림해 품목에 나눕니다. 이렇게 나눈 값의 합이 청구액과 다르면 그 차이(단수)를 마지막 품목에 더하거나 빼서 합을 맞추고, 그 금액을 ‘단수 조정’ 으로 따로 남깁니다. 어느 품목이 흡수했는지가 늘 같은 규칙(마지막 품목)이라 다시 계산해도 같은 결과가 나옵니다.

점검 판정 규칙

판정 조건결과 상태사용자 조치
L01 — 장부 취득원가와 산출 수입 원가에 차이가 있음점검 필요차이 항목을 표준 입고·송장 문서에서 확인
L02 — 실제 부대비용이 예정 대비 허용 범위(±10%, 가정값)를 넘음점검 필요예정 단가와 실제 청구 내역 확인
L03 — 환급 가능 수입 부가가치세가 장부 취득원가에 포함된 것으로 보임점검 필요취득원가 제외 처리 여부 확인
L04 — 배부 기준(중량) 값이 빈 품목이 있음점검 필요품목 마스터의 중량 확인
위 조건이 없음정상조치 없음

조회조건

조건필수기본값조회 조건으로 보내는 방식
입고 연월필수202610Period eq '202610'
통화선택전체(조건 없음)Currency eq 'USD'
점검 상태선택전체(조건 없음)CheckStatus eq 'CHECK'
B/L 일자 부터선택비움BlDate ge datetime'…'
B/L 일자 까지선택비움BlDate le datetime'…'

“전체” 는 코드값을 보내지 않고 해당 조건을 조회 조건에서 뺍니다. 환율과 관세율은 샘플의 가정값이며 실제 고시값이 아닙니다.

결과 컬럼

탭컬럼산식·의미
B/L 원가 확정외화 금액 · 가정 환율 · 물품 대가 · 예정/실제 부대비용 · 차이 · 차이율 · 수입 원가 · 장부 대비 차이차이율 = (실제 − 예정) ÷ 예정
품목별 배부수량 · 중량 · 물품 대가 · 운임 · 보험료 · 관세 · 통관수수료 · 하역·보관 · 배부 합계 · 수입 원가 · 단위 원가단위 원가 = 수입 원가 ÷ 수량
부대비용 명세비용 · 배부 기준 · 원가 포함 · 예정 · 실제 · 차이수입 부가가치세는 원가 제외
대사 결과구분 · 대사 · 좌변 · 우변 · 검사 건수 · 차이 건수 · 최대 차이통화별 대사는 통화마다 따로 계산

좁은 화면에서 달라지는 것

이 화면은 표가 중심이라 1,280px 안팎 이상의 폭을 기준으로 구성했습니다. 폭이 좁아지면 표를 좌우로 밀어 가며 봅니다. 휴대폰 전용 배치는 따로 두지 않았습니다. 회의실 화면이나 노트북에서 쓰는 점검 화면으로 보시는 것이 좋습니다.

파일 구성

구분내용
앱 본체index.html · manifest.json · Component.js · controller · view · model · css · i18n
서비스서비스 정의 · 서비스 로직 · 검증용 샘플 데이터
설명서·영상설명서 한 파일 · 소개 영상과 대표 이미지

SAP 표준 기능 확장 포인트

이 앱은 SAP 표준을 대체하지 않습니다. 표준이 이미 담당하는 일은 표준 T-code 에 두고, B/L 한 건을 단위로 묶어 보는 관점만 더하는 쪽으로 만들었습니다. 어디까지가 표준이고 어디서부터 이 화면인지를 먼저 적습니다.

표준으로 되는 것과 안 되는 것

하고 싶은 일SAP 표준표준 화면의 단위이 앱이 더하는 관점
구매오더의 물품 대가·예정 부대비용 확인ME23N구매오더 문서와 품목B/L 한 건에 묶인 구매오더의 예정 합계를 한 줄로 봅니다
입고 시점 취득원가 확인MIGO · MB51자재 문서 한 건 · 문서 목록품목 수입 원가를 배부 결과와 나란히 놓습니다
부대비용 송장 반영MIRO송장 한 장송장 합계가 품목 배부 합계와 같은지 대사합니다
입고·송장 차이 정리MR11GR/IR 계정 정산 실행정리 전에 차이가 어느 B/L 에서 났는지 먼저 좁힙니다
B/L 한 건 단위의 원가 확정 점검—문서 단위 화면을 오가며 사용자가 묶어 봅니다예정·실제·배부·수입 원가·장부 차이를 B/L 한 줄에 놓습니다
중량·가액·수량 기준 배부 비교와 단수 표시—보통 엑셀에서 계산합니다비용마다 기준을 적용해 품목에 나누고 단수 조정액을 따로 보입니다

T-code 별 연계 지점

맞닿은 표준 T-code 마다 이 앱이 이어받는 데이터, 두 화면의 숫자를 맞춰 보는 지점, 오가는 방법, 표준에 남겨 둘 일을 적었습니다.

T-code이름이어받는 데이터숫자를 맞춰 보는 지점오가는 방법표준에 남겨 둘 일
ME23N구매오더 조회EKKO · EKPO 의 외화 금액과 예정 부대비용물품 대가(외화) · 예정 부대비용 합계이 앱의 B/L 행 → 구매오더 번호로 ME23N 에서 원천 확인구매오더 변경·승인
MIGO상품 입고MSEG 의 입고 수량과 취득원가품목 수량 · 장부 취득원가품목 행 → 입고 문서를 MIGO 에서 조회입고 전기·취소
MIRO송장 검증RBKP · RSEG 의 부대비용 송장 라인실제 부대비용 = 부대비용 송장 합계부대비용 명세 행 → 송장 번호로 MIRO 에서 확인송장 검증·지급 전기
MB51자재 문서 목록MSEG 의 금액·수량 이력품목 장부 취득원가 합계이 앱의 장부 대비 차이 → MB51 목록에서 원천 문서 확인문서 이력 조회·감사 대응
MR11GR/IR 계정 정산입고·송장 차이 문서예정과 실제의 차이가 정산 대상과 맞는지차이 큰 B/L 을 좁힌 뒤 표준 정산 실행정산 실행과 전표 생성

운영으로 옮길 때 가장 자주 나오는 질문은 “기존 리포트를 없애야 하나” 입니다. 없애지 않습니다. 표준 화면은 전표를 만들고 문서를 추적하는 실행과 감사 대응의 자리로 그대로 두고, 이 앱은 마감 전에 B/L 단위로 원가를 점검하는 자리로 함께 씁니다. 두 화면의 숫자가 다르면 위 표의 ‘맞춰 보는 지점’ 으로 되돌아가 원천을 확인합니다. 법정 보고와 공시, 관세·부가가치세 신고에 쓰는 수치는 표준과 회사 절차를 따릅니다.

S/4HANA 분석 스택과의 자리

S/4HANA 에는 구매 문서와 재고 원가를 분석하는 표준 CDS 뷰와 Fiori 분석 앱, Analysis for Office 같은 도구가 있습니다. 이 앱은 그 도구들과 경쟁하지 않습니다. 표준 분석이 구매오더·자재 문서·송장을 각각의 관점에서 보여 준다면, 이 앱은 B/L 한 건에 모인 비용을 품목 원가로 풀어 장부와 견주는 점검 관점을 보탭니다. 아래 CDS 절의 뷰는 같은 원천 테이블을 읽는 별도 뷰이므로 표준 뷰를 고치지 않습니다. 표준 CDS 뷰와 Fiori 앱 중 이번 환경에서 확인하지 못한 이름은 이 글에 적지 않았습니다 — 실제 이름은 “확인 필요” 로 남기고 원천 테이블 기준으로 설계했습니다.

확장 포인트 — 운영에서 실제로 손대는 자리

자리무엇을 손대나어떻게
부대비용 조건 유형어떤 조건 유형(운임·보험·관세·통관·하역)을 원가 포함 비용으로 볼지매핑 테이블에 유형별 한 줄을 추가합니다
배부 기준비용 유형마다 중량·가액·수량 중 무엇으로 나눌지같은 매핑 테이블의 기준 컬럼으로 정합니다
B/L 연결선하증권 번호와 구매오더·송장을 어떻게 잇는지고객사의 B/L 관리 방식(확장 필드·커스텀 필드·연결 테이블)에 맞춰 연결 뷰를 둡니다. 확인 필요
환율 유형·시점물품 대가를 환산하는 환율 유형과 기준일샘플은 가정 환율 고정값. 운영에서는 환율 테이블을 읽는 연결로 바꿉니다
허용 범위예정 대비 실제 차이를 점검 필요로 볼 기준(샘플 ±10%)서비스 로직의 판정 상수 한 곳
권한구매조직·플랜트별로 보이는 B/L 범위CDS 권한 정의에 표준 권한 오브젝트를 겁니다

요구사항 매핑표

기준서요구사항대응 기능원천 데이터비고
IAS 2 재고자산(K-IFRS 제1002호)매입원가에 매입가격·수입관세·취득과 직접 관련된 운송·취급 비용을 포함하고 환급 가능 세금은 제외수입 원가 산출과 환급 가능 부가가치세 제외 표시EKPO · MSEG · RSEG문단번호는 원문 확인 후 기재
IAS 2 재고자산(K-IFRS 제1002호)취득원가를 품목에 합리적 기준으로 배부품목별 중량·가액·수량 배부와 단수 조정MSEG판단은 회사와 감사인

CDS 구성

이 사례의 화면은 서비스 로직이 샘플 데이터로 배부와 대사를 계산합니다. 운영에서는 그 계산의 대부분을 CDS 로 내립니다. 아래는 그때 만드는 뷰와 권한의 구성입니다. B/L 번호는 표준 키가 아니므로, 고객사가 B/L 을 구매오더·송장에 어떻게 잇는지가 먼저 정해져야 합니다(아래 코드의 B/L 연결 테이블은 그 자리를 대신한 스케치입니다).

코드는 스케치입니다. 필드 이름과 표준 객체 이름은 릴리스와 환경에 따라 다르므로, 그대로 붙여 넣기 전에 실제 이름을 확인해야 합니다. 확인이 필요한 자리는 주석에 적어 두었습니다.

뷰 레이어 구성

레이어뷰하는 일왜 나누나
기준ZIMP_COSTBASIS · ZIMP_BLHEAD · ZIMP_BLCOST비용 유형 → 배부 기준·원가 포함 매핑, B/L 헤더, B/L 부대비용기준을 코드에 박으면 새 비용 유형이 생길 때마다 개발자를 부르게 됩니다.
차원ZI_ImportCostType비용 유형 한 행 + 기준 + 포함 여부 + 텍스트큐브에서 join 을 한 번만 걸고 텍스트와 값 도움말이 이 뷰 하나를 봅니다.
집계ZI_ImportBlBasis · ZI_ImportBlCostByBasisB/L 별 기준 값 합계와 기준별 부대비용 합계배부 식의 분모와 분자를 B/L 단위에서 한 번만 정의합니다.
큐브ZI_ImportItemAlloc · ZI_ImportLandedItem품목별 배부, 단수 조정, 수입 원가화면이 계산하던 배부를 DB 로 내리고 단수 규칙을 한 곳에 둡니다.
쿼리ZC_ImportLandedQuery조회조건·표시 컬럼·필터 기본값표준 Fiori 와 Analysis for Office 도 같은 쿼리를 띄웁니다.
권한ZI_ImportLandedItem (DCL)구매조직·플랜트 권한집계를 읽는 자리에 걸어야 합계로 새지 않습니다.
서비스ZUI_ImportLandedCost서비스 정의와 OData V2 바인딩화면의 manifest 서비스 주소가 가리킬 자리입니다.

① 비용 유형 → 배부 기준 매핑 테이블

리포트의 모든 숫자가 이 테이블에서 갈립니다. 어떤 비용을 원가에 넣고 무엇으로 나눌지를 정하는 자리라 운영 전환에서 가장 먼저 합의해야 하는 항목입니다. 유효기간을 둔 이유는 조건 유형 체계가 바뀌어도 과거 입고분의 원가가 그때 기준으로 다시 계산되게 하기 위해서입니다.

// ────────────────────────────────────────────────────────────────
//  ZIMP_COSTBASIS — 비용 유형 → 배부 기준 · 원가 포함 매핑 (투명 테이블)
//  운영에서는 구매 조건 유형(운임·보험·관세·통관·하역)을 그대로 옮겨 담는다.
//  코드에 박지 않는 이유 : 새 비용 유형이 생길 때마다 개발자를 부르게 되면
//  원가 점검 화면은 금방 낡는다.
// ────────────────────────────────────────────────────────────────
@EndUserText.label : '수입 부대비용 배부 기준'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #C          // 고객 유지 — 전송(TR)으로 옮긴다
@AbapCatalog.dataMaintenance : #ALLOWED  // 유지보수 뷰를 함께 만들어 둔다
define table zimp_costbasis {
  key mandt      : mandt not null;
  key cost_type  : abap.char(4) not null;   // FRT 운임 · INS 보험 · DUT 관세 · CLR 통관 · HDL 하역 · VAT 수입 부가세
  key valid_from : abap.dats not null;
  valid_to       : abap.dats;
  basis          : abap.char(1);            // W 중량 · V 가액 · Q 수량
  incl_cost      : abap.char(1);            // X = 원가 포함, 공백 = 제외(환급 가능 세금 등)
  sort_no        : abap.int4;
}

// ── B/L 연결 : 선하증권은 표준 키가 아니므로 고객사 방식에 맞춰 둔다(확인 필요)
@EndUserText.label : '수입 B/L 헤더'
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table zimp_blhead {
  key mandt    : mandt not null;
  key bl_no    : abap.char(20) not null;
  ebeln        : ebeln;                      // 구매오더
  waers        : waers;                      // 거래 통화
  fx_amount    : abap.curr(15,2);            // 외화 금액
  bl_date      : abap.dats;
  period       : abap.char(6);               // 입고 연월 YYYYMM
}

@EndUserText.label : '수입 B/L 부대비용'
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table zimp_blcost {
  key mandt    : mandt not null;
  key bl_no    : abap.char(20) not null;
  key cost_no  : abap.numc(2) not null;
  cost_type    : abap.char(4);
  waers        : waers;
  plan_amount  : abap.curr(15,2);            // 예정 — 구매오더 조건에서
  act_amount   : abap.curr(15,2);            // 실제 — 송장 검증 라인에서
}

② 비용 유형 차원 뷰

비용 유형마다 배부 기준과 원가 포함 여부를 한 행으로 가져오는 뷰입니다. 큐브가 매핑 테이블을 직접 읽으면 유효기간 조건이 뷰마다 흩어지므로, 유효기간 판단을 이 뷰 한 곳에 모았습니다.

// ────────────────────────────────────────────────────────────────
//  ZI_ImportCostType — 비용 유형 차원
//  배부 기준·원가 포함 여부·표시 순서를 한 행으로 낸다.
//  유효기간 판단은 여기서 한 번만 한다 — 큐브마다 흩어 두면 어긋난다.
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '수입 비용 유형'
@ObjectModel.representativeKey : 'CostType'
@Analytics.dataCategory : #DIMENSION
define view entity ZI_ImportCostType
  as select from zimp_costbasis as b
{
      @ObjectModel.text.element : ['CostTypeName']
  key b.cost_type as CostType,
      b.basis     as AllocBasis,          // W · V · Q
      case b.incl_cost when 'X' then 'Y' else 'N' end as InclCost,
      b.sort_no   as SortNo,
      // 이름은 텍스트 테이블을 따로 두거나 도메인 고정값 텍스트를 쓴다 — 확인 필요
      cast( b.cost_type as abap.char(40) ) as CostTypeName
}
where b.valid_from <= $session.system_date
  and ( b.valid_to  is initial or b.valid_to >= $session.system_date )

③ B/L 단위 합계 — 배부 식의 분모와 분자

품목 배부는 비용 ÷ 기준 값 합계 × 품목 기준 값입니다. 이 가운데 분모(기준 값 합계)와 분자의 큰 덩어리(기준별 비용 합계)는 B/L 단위로 한 번만 계산하면 됩니다. 별도 뷰로 두면 큐브는 분수 곱셈만 합니다. 기준 값이 비어 있는 품목은 합계에서 빠지므로 판정(L04)에서 따로 잡습니다.

// ────────────────────────────────────────────────────────────────
//  ZI_ImportBlBasis — B/L 별 기준 값 합계 (분모)
//  중량·가액·수량을 B/L 단위로 더하고, 단수를 흡수할 마지막 품목 번호를 함께 낸다.
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '수입 B/L 기준 값 합계'
define view entity ZI_ImportBlBasis
  as select from ekpo as i
    inner join   zimp_blhead as h on h.ebeln = i.ebeln
{
  key h.bl_no                                   as BlNo,
      sum( cast( i.brgew as abap.dec(23,3) ) )  as TotWeight,   // 총중량 — 필드는 확인 필요
      sum( cast( i.netwr as abap.dec(23,2) ) )  as TotValue,    // 물품 대가 합계
      sum( cast( i.menge as abap.dec(23,3) ) )  as TotQty,
      max( i.ebelp )                            as LastItemNo   // 단수를 흡수할 마지막 품목
}
group by h.bl_no

// ────────────────────────────────────────────────────────────────
//  ZI_ImportBlCostByBasis — B/L · 배부 기준별 부대비용 합계 (분자)
//  원가에 넣지 않는 비용(환급 가능 수입 부가가치세)은 여기서 걸러 낸다.
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '수입 B/L 기준별 부대비용'
define view entity ZI_ImportBlCostByBasis
  as select from zimp_blcost as c
    inner join   ZI_ImportCostType as t on t.CostType = c.cost_type
{
  key c.bl_no       as BlNo,
  key t.AllocBasis  as AllocBasis,                               // W · V · Q
      sum( c.act_amount ) as CostAct
}
where t.InclCost = 'Y'
group by c.bl_no, t.AllocBasis

④ 품목 배부 큐브 — 수입 원가가 만들어지는 곳

이 뷰에서 품목 수입 원가가 결정됩니다. 기준별 비용 합계에 품목 비율을 곱해 원 단위로 반올림하고, B/L 에서 반올림한 값의 합과 청구액의 차이(단수)를 마지막 품목에 더합니다. 단수 규칙을 이 한 뷰에 둔 덕분에 화면·CSV·AI 연계 어디에서 읽어도 같은 숫자가 나옵니다.

// ────────────────────────────────────────────────────────────────
//  ZI_ImportItemAlloc — 품목별 기준별 배부 (반올림 값)
//  배부액 = round( 기준별 부대비용 × 품목 기준 값 ÷ B/L 기준 값 합계 , 0 )
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '수입 품목 기준별 배부'
define view entity ZI_ImportItemAlloc
  as select from ekpo as i
    inner join   zimp_blhead         as h on h.ebeln = i.ebeln
    inner join   ZI_ImportBlBasis    as b on b.BlNo  = h.bl_no
    left outer join ZI_ImportBlCostByBasis as cw on cw.BlNo = h.bl_no and cw.AllocBasis = 'W'
    left outer join ZI_ImportBlCostByBasis as cv on cv.BlNo = h.bl_no and cv.AllocBasis = 'V'
    left outer join ZI_ImportBlCostByBasis as cq on cq.BlNo = h.bl_no and cq.AllocBasis = 'Q'
{
  key h.bl_no    as BlNo,
  key i.ebelp    as ItemNo,
      b.LastItemNo,
      @Semantics.amount.currencyCode : 'Currency'
      cast( round( division( coalesce( cw.CostAct, 0 ) * cast( i.brgew as abap.dec(23,3) ),
                             b.TotWeight, 4 ), 0 ) as abap.curr(15,2) ) as AllocByWeight,
      @Semantics.amount.currencyCode : 'Currency'
      cast( round( division( coalesce( cv.CostAct, 0 ) * cast( i.netwr as abap.dec(23,2) ),
                             b.TotValue, 4 ), 0 ) as abap.curr(15,2) )  as AllocByValue,
      @Semantics.amount.currencyCode : 'Currency'
      cast( round( division( coalesce( cq.CostAct, 0 ) * cast( i.menge as abap.dec(23,3) ),
                             b.TotQty, 4 ), 0 ) as abap.curr(15,2) )    as AllocByQty,
      h.waers as Currency
}

// ────────────────────────────────────────────────────────────────
//  ZI_ImportBlRoundSum — B/L 별 반올림 합계와 청구액의 차이(단수)
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #NOT_REQUIRED
@EndUserText.label : '수입 B/L 단수'
define view entity ZI_ImportBlRoundSum
  as select from ZI_ImportItemAlloc as a
    inner join   ZI_ImportBlCostByBasis as c on c.BlNo = a.BlNo
{
  key a.BlNo,
      sum( a.AllocByWeight + a.AllocByValue + a.AllocByQty ) as AllocRounded,
      sum( distinct c.CostAct )                               as CostActTotal   // 확인 필요 : 기준별 행 중복 주의
}
group by a.BlNo

// ────────────────────────────────────────────────────────────────
//  ZI_ImportLandedItem — 품목 수입 원가 (큐브)
//  수입 원가 = 물품 대가(원화) + 배부 합계 + 단수 조정(마지막 품목만)
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #CHECK
@EndUserText.label : '수입 품목 원가'
@Analytics.dataCategory : #CUBE
@ObjectModel.usageType : { serviceQuality : #C, sizeCategory : #XL, dataClass : #TRANSACTIONAL }
define view entity ZI_ImportLandedItem
  as select from ZI_ImportItemAlloc as a
    inner join   ekpo               as i on i.ebelp = a.ItemNo
    inner join   zimp_blhead        as h on h.bl_no = a.BlNo and h.ebeln = i.ebeln
    inner join   ZI_ImportBlRoundSum as r on r.BlNo = a.BlNo
  association [0..*] to ZI_ImportCostType as _CostType on 1 = 1
{
  key a.BlNo,
  key a.ItemNo,
      h.period                                           as Period,
      i.werks                                            as Plant,
      i.ekorg                                            as PurchasingOrg,   // 확인 필요 : 헤더 필드일 수 있음
      @Semantics.amount.currencyCode : 'Currency'
      i.netwr                                            as GoodsFx,
      @Semantics.amount.currencyCode : 'Currency'
      ( a.AllocByWeight + a.AllocByValue + a.AllocByQty ) as AllocBase,
      // 단수 : 마지막 품목이 청구액과 반올림 합계의 차이를 흡수한다
      @Semantics.amount.currencyCode : 'Currency'
      case when a.ItemNo = a.LastItemNo
           then r.CostActTotal - r.AllocRounded
           else cast( 0 as abap.curr(15,2) ) end         as RoundAdj,
      a.Currency,
      _CostType
}

⑤ 분석 쿼리 — 조회조건과 표시 컬럼

큐브를 그대로 노출하면 사용자가 필터와 컬럼을 처음부터 짜야 합니다. 쿼리 뷰는 입고 연월을 필수 조건으로 두고, 통화·점검 상태를 선택 조건으로, 배부 합계와 수입 원가를 기본 컬럼으로 정합니다. 대용량에서 연월 조건 없이 전체를 읽는 일을 막는 장치이기도 합니다.

// ────────────────────────────────────────────────────────────────
//  ZC_ImportLandedQuery — 조회·점검 쿼리
//  입고 연월은 필수 필터. 연월 없이 전 기간을 읽지 못하게 막는다.
// ────────────────────────────────────────────────────────────────
@AccessControl.authorizationCheck : #CHECK
@EndUserText.label : '수입 원가 확정 점검'
@Analytics.query : true
@VDM.viewType : #CONSUMPTION
define view entity ZC_ImportLandedQuery
  as select from ZI_ImportLandedItem
{
  @AnalyticsDetails.query.axis : #ROWS
  @Consumption.filter : { selectionType : #SINGLE, mandatory : true, multipleSelections : false }
  Period,

  @AnalyticsDetails.query.axis : #ROWS
  @AnalyticsDetails.query.displayHierarchy : #OFF
  BlNo,

  @AnalyticsDetails.query.axis : #ROWS
  ItemNo,

  @Consumption.filter : { selectionType : #SINGLE, mandatory : false }
  Currency,

  @AnalyticsDetails.query.axis : #COLUMNS
  @Aggregation.default : #SUM
  GoodsFx,

  @AnalyticsDetails.query.axis : #COLUMNS
  @Aggregation.default : #SUM
  AllocBase,

  @AnalyticsDetails.query.axis : #COLUMNS
  @Aggregation.default : #SUM
  RoundAdj
}

⑥ 권한 (DCL) — 집계를 읽는 자리에 건다

권한은 쿼리가 아니라 큐브에 겁니다. 쿼리에만 걸면 다른 경로로 큐브를 읽을 때 구멍이 생기고, 드릴스루에만 걸면 합계에서 뺄셈으로 다른 조직의 숫자를 추정할 수 있습니다. 표준 구매 권한 오브젝트(플랜트)를 그대로 재사용하므로 새 역할을 만들지 않고 기존 구매 담당 역할에 조회 권한만 더하면 됩니다.

// ────────────────────────────────────────────────────────────────
//  ZI_ImportLandedItem (DCL) — 플랜트 기준 조회 권한
//  M_BEST_WRK : 구매 문서 — 플랜트 단위 권한(표준 오브젝트, 필드는 확인 필요)
// ────────────────────────────────────────────────────────────────
@EndUserText.label : '수입 품목 원가 권한'
@MappingRole : true
define role ZI_ImportLandedItem {
  grant select on ZI_ImportLandedItem
    where ( Plant ) = aspect pfcg_auth( M_BEST_WRK, WERKS, ACTVT = '03' );
}

⑦ 서비스 정의 — 화면이 부르는 서비스

마지막으로 쿼리를 서비스로 노출합니다. 서비스 정의는 무엇을 내보낼지를, 서비스 바인딩은 어떤 프로토콜(OData V2)로 낼지를 정합니다. 바인딩을 게시하고 나면 화면의 앱 설정(manifest)에 적힌 서비스 주소를 이 서비스 주소로 바꾸면 샘플 서비스 대신 운영 데이터가 붙습니다.

// ────────────────────────────────────────────────────────────────
//  ZUI_ImportLandedCost — 서비스 정의
//  서비스 바인딩(OData V2 - UI)은 ADT 에서 이 정의를 골라 만들고 게시한다.
//  기존 방식으로 활성화한다면 /IWFND/MAINT_SERVICE 에서 등록한다(확인 필요).
// ────────────────────────────────────────────────────────────────
@EndUserText.label : '수입 원가 확정 점검 서비스'
define service ZUI_ImportLandedCost {
  expose ZC_ImportLandedQuery as LandedItem;
  expose ZI_ImportCostType    as CostType;
}

운영 시점에 해야 할 일

개발보다 정하는 일이 많습니다. 아래는 코드를 쓰기 전에 합의해야 하는 항목입니다.

해야 할 일무엇을 정하나정하지 않으면누가
부대비용 조건 유형 매핑운임·보험·관세·통관·하역 조건 유형을 어느 비용으로 보고 원가에 넣을지같은 비용이 B/L 마다 다르게 분류되어 원가가 흔들립니다구매팀 · 회계팀
배부 기준비용 유형마다 중량·가액·수량 중 무엇으로 나눌지사람마다 기준이 달라 품목 원가가 어긋납니다회계팀 · 구매팀
B/L 연결 방식선하증권 번호를 구매오더·송장과 어떻게 이을지(확장 필드·연결 테이블)부대비용이 어느 B/L 의 것인지 알 수 없어 배부 자체가 안 됩니다구매팀 · 개발
환율 유형과 환산 시점물품 대가를 환산하는 환율 유형과 기준일같은 B/L 의 물품 대가가 화면마다 달라집니다자금팀 · 회계팀
부호·통화 규칙외화 금액과 원화 금액의 표시 규칙, 통화별 소수 자릿수통화별 대사에서 자릿수 차이가 차이로 잡힙니다회계팀
원천 확정(실적·예정)예정은 구매오더 조건, 실제는 송장 검증 라인으로 확정예정과 실제가 섞여 차이율이 의미를 잃습니다구매팀 · 회계팀
허용 범위예정 대비 실제 차이를 점검 필요로 볼 기준(샘플 ±10%)점검 필요가 너무 많거나 너무 적게 뜹니다구매팀 · 회계팀
권한 설계구매조직·플랜트별로 볼 수 있는 B/L 범위다른 조직의 수입 원가가 드러납니다보안 · 권한
대사 체계표준 T-code(MB51 · MIRO)와 맞출 항목과 주기숫자가 다를 때 어디부터 볼지 합의가 없습니다회계팀
전송(TR) 순서매핑 테이블 → 차원·집계 뷰 → 큐브 → 쿼리 → 권한 → 서비스의존 뷰가 없어 활성화 오류가 납니다개발 · Basis
서비스 활성화서비스 바인딩 게시(또는 서비스 등록)와 앱 설정의 서비스 주소 교체화면이 운영 서비스를 찾지 못해 서비스 정보 오류가 납니다Basis · 개발

운영 데이터로 갈 때 — B/L 과 문서가 수천만 건이면

샘플은 B/L 7건, 품목 18건입니다. 운영에서는 구매오더 품목과 자재 문서가 수천만 건이 될 수 있습니다. 그때 먼저 지킬 원칙은 세 가지입니다. 첫째, 집계는 DB 에서 합니다 — 위 뷰가 그 일을 하므로 화면이 문서를 모두 내려받아 합산하지 않습니다. 둘째, 입고 연월을 필수 조건으로 둡니다 — 쿼리의 필수 필터가 전 기간 조회를 막습니다. 셋째, 조회는 B/L 요약부터 읽고 품목과 비용은 행을 눌렀을 때 읽습니다. 응답 시간 기준(예: 월 단위 요약은 수 초 이내)은 고객사 데이터로 측정해 정해야 하며, 이 글은 측정값을 약속하지 않습니다. 인덱스는 B/L 번호·구매오더 번호·입고 연월에 필요한지 실행 계획을 보고 판단합니다.

자주 묻는 질문

도입 상담과 데모에서 자주 받는 질문들을 네 묶음으로 적었습니다.

숫자와 산식

수입 원가는 어떻게 계산합니까?

선하증권 한 건마다 외화 금액 × 가정 환율로 원화 물품 대가를 구하고, 그 B/L 에 모인 부대비용 가운데 원가에 포함하는 것만 품목에 나눠 더합니다. 즉 수입 원가는 물품 대가 + 배부 부대비용입니다. 환급 가능한 수입 부가가치세는 원가에서 제외합니다.

예를 들어 샘플의 BL-0001 은 물품 대가 112,355,940원, 부대비용 14,323,190원으로 수입 원가가 126,679,130원입니다.

부대비용은 어떤 기준으로 품목에 나눕니까?

비용마다 기준이 정해져 있습니다. 해상운임과 하역·보관은 중량, 보험료와 관세는 가액, 통관수수료는 수량으로 나눕니다. 품목의 기준 값을 B/L 의 기준 값 합계로 나눈 비율을 비용에 곱하는 방식입니다.

이 기준은 샘플의 기본값이며 회사마다 다를 수 있습니다. 운영에서는 비용 유형별 기준을 매핑 테이블에 두므로 코드를 고치지 않고 바꿀 수 있습니다.

나누고 남는 단수는 어떻게 처리합니까?

비용을 품목에 나눌 때 원 단위로 반올림하면 품목 배부액의 합이 청구액과 몇 원씩 어긋날 수 있습니다. 이 앱은 그 차이를 마지막 품목에 더하거나 빼서 합을 청구액과 맞추고, 조정한 금액을 ‘단수 조정’ 으로 따로 보여 줍니다. 어느 품목이 흡수했는지가 늘 같은 규칙이라 다시 계산해도 결과가 같습니다.

환급 가능한 수입 부가가치세는 왜 원가에서 뺍니까?

환급받을 세금은 비용이 아니므로 재고 원가에 넣지 않는다는 것이 관련 기준서의 취지입니다. 이 앱은 부대비용 명세에서 수입 부가가치세 줄을 ‘제외(환급 가능)’ 로 표시하고 수입 원가 계산에서 뺍니다. 장부 취득원가가 이 세금만큼 크게 잡혀 있으면 점검 필요로 띄웁니다.

환급 가능 여부의 판단은 회사와 세무 대리인이 합니다. 이 화면은 그 판단을 대신하지 않고 원가에 섞였는지만 점검합니다.

외화와 환율은 어떻게 다룹니까?

물품 대가는 B/L 의 통화로 들어 있으므로 B/L 마다 외화 금액에 환율을 곱해 원화로 옮깁니다. 서로 다른 통화의 외화 금액은 그대로 더하지 않고, 합계는 원화 환산 금액으로만 냅니다. 대사 결과 탭에서는 통화마다 따로 환산 대사를 합니다.

샘플의 환율은 화면 시연용 가정값이며 실제 고시 환율이 아닙니다. 운영에서는 환율 유형과 환산 시점을 정해 환율 테이블에서 읽도록 바꿉니다.

‘점검 필요’ 는 어떤 조건에서 뜹니까?

네 가지입니다. 장부 취득원가와 산출한 수입 원가가 다를 때(L01), 실제 부대비용이 예정 대비 허용 범위(샘플 ±10%)를 넘을 때(L02), 환급 가능 수입 부가가치세가 장부 취득원가에 포함된 것으로 보일 때(L03), 배부 기준인 중량이 빈 품목이 있을 때(L04)입니다. 어느 조건에도 걸리지 않으면 정상입니다.

상세 창 위쪽에 판정 사유가 문장으로 적혀 있어, 어디부터 확인할지 바로 알 수 있습니다.

화면과 조작

조회조건에서 꼭 넣어야 하는 것은 무엇입니까?

입고 연월 하나입니다. 기본값이 들어 있으므로 바꾸지 않고 조회 버튼만 눌러도 됩니다. 통화, 점검 상태, B/L 일자(부터·까지)는 선택 조건이며 비워 두면 조건에서 빠집니다. ‘전체’ 를 고르는 것도 같은 뜻입니다.

입력 칸에서 Enter 키를 눌러도 같은 조회가 실행되고, 초기화 버튼은 조건을 처음 상태로 돌립니다.

조회한 뒤 어느 탭부터 보면 됩니까?

위쪽 요약에서 점검 필요 건수를 먼저 보고, B/L 원가 확정 탭에서 상태가 점검 필요인 행을 찾는 순서를 권합니다. 그 행을 눌러 상세 창에서 이유를 확인하고, 필요하면 품목별 배부와 부대비용 명세 탭에서 숫자를 거슬러 올라갑니다. 마지막으로 대사 결과 탭에서 정합성 대사에 차이가 없는지 봅니다.

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

선하증권 상세 창이 열립니다. 거래처, 인코텀즈, 통화, B/L 일자와 입고일, 물품 대가, 실제 부대비용, 배부 합계와 단수 조정, 수입 원가, 장부 취득원가, 환급 가능 수입 부가가치세, 점검 결과가 위쪽에 있고 그 아래에 품목별 배부와 부대비용 명세가 이어집니다. 닫기 버튼이나 창 바깥을 누르면 원래 탭으로 돌아갑니다.

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

하단 CSV 내려받기 버튼은 B/L 원가 확정, 품목별 배부, 부대비용 명세 탭에서 지금 보고 있는 탭의 내용을 UTF-8 CSV 로 저장합니다. 조회 조건에 맞는 행만 담기고 첫 줄에 컬럼 머리글이 붙습니다. 엑셀에서 한글이 깨지면 열 때 인코딩을 UTF-8 로 지정하시기 바랍니다.

휴대폰이나 좁은 화면에서도 쓸 수 있습니까?

표 중심 화면이라 노트북이나 회의실 화면을 기준으로 구성했습니다. 폭이 좁으면 표를 좌우로 밀어 가며 볼 수 있지만, 휴대폰 전용 배치는 따로 두지 않았습니다. 이동 중 확인이 필요하면 CSV 로 내려받아 쓰는 편이 낫습니다.

표준 T-code 와 데이터

표준 T-code 를 계속 써야 합니까? 기존 리포트를 없애야 합니까?

없애지 않습니다. 구매오더 변경(ME23N), 입고 전기(MIGO), 송장 검증(MIRO), GR/IR 정산(MR11) 같은 실행은 표준 T-code 가 계속 담당합니다. 이 화면은 마감 전에 B/L 단위로 원가를 점검하는 관점을 더해 함께 씁니다.

법정·공시·세무 신고에 쓰는 수치는 표준과 회사 절차를 따르고, 이 화면의 결과는 점검 자료로 씁니다.

이 화면 숫자가 표준 화면과 다르면 어디를 봅니까?

자재 문서 목록(MB51)에서 품목의 취득원가를, 송장 검증(MIRO)에서 부대비용 송장 라인을, 구매오더(ME23N)에서 물품 대가와 예정 부대비용을 확인합니다. 이 앱의 장부 대비 차이는 두 숫자의 차이를 보여 줄 뿐 원인을 단정하지 않으므로, 차이가 난 B/L 의 상세 창에서 품목과 비용을 나눠 어느 쪽이 다른지 좁힌 뒤 해당 T-code 로 원천을 봅니다.

데이터 원천은 무엇이고 정합성은 어떻게 확인합니까?

원천은 구매오더(EKKO · EKPO), 자재 문서(MSEG), 송장 검증(RBKP · RSEG), 회계 전표(BKPF · BSEG)입니다. 정합성은 대사 결과 탭에서 확인합니다. 배부 전 부대비용과 배부액 합계, 예정+차이와 실제, 수입 원가의 구성, 품목 합계와 B/L 합계, 장부와 산출 원가, 통화별 환산을 항목마다 검사 건수·차이 건수·최대 차이로 적습니다.

부대비용 조건 유형이나 계정 체계가 바뀌면 어떻게 합니까?

비용 유형과 배부 기준은 코드가 아니라 매핑 테이블에 있으므로, 새 유형이 생기면 한 줄을 추가하고 기준과 원가 포함 여부를 적으면 됩니다. 유효기간을 두었기 때문에 과거 입고분은 그때의 기준으로 다시 계산됩니다. 계정이 바뀌어 장부 취득원가를 읽는 위치가 달라지면 원천 연결 뷰를 확인해야 합니다.

적용 시기와 범위는 어떻게 됩니까?

이 화면은 점검 도구라 적용 시기가 따로 없습니다. 관련 기준서 IAS 2 재고자산(K-IFRS 제1002호)의 시행일과 경과규정은 원문을 확인한 뒤 적용 범위를 정해야 하며, 이 글은 해당 내용을 다루지 않습니다. 화면의 점검 항목은 회사의 수입 원가 정책에 맞춰 조정해서 씁니다.

도입과 운영

도입하면 무엇이 달라지고 누가 씁니까?

수입 담당자와 회계 담당자가 마감 전에 쓰는 화면입니다. B/L 마다 엑셀로 배부를 다시 계산하고 장부와 맞추던 일이 한 화면의 조회와 상세 확인으로 줄어듭니다. 점검 필요 B/L 을 먼저 골라 볼 수 있어 확인 순서가 정해지고, 같은 기준으로 계산되므로 담당자마다 숫자가 달라지는 일이 줄어듭니다.

운영 시스템에 연결하는 절차와 소요는 어떻게 됩니까?

순서는 정해져 있습니다. 비용 유형·배부 기준·B/L 연결 방식을 합의하고, CDS 뷰와 권한을 만들어 전송한 뒤, 서비스를 게시하고, 화면의 앱 설정에 적힌 서비스 주소를 운영 서비스로 바꿉니다. 소요는 B/L 연결 방식과 합의 속도에 달려 있어 이 글에서 기간을 약속하지 않습니다. 개발보다 정하는 일이 더 많다는 점은 ‘운영 시점에 해야 할 일’ 표에 정리했습니다.

권한과 보안은 어떻게 됩니까?

집계를 읽는 큐브에 표준 구매 권한(플랜트 등)을 겁니다. 쿼리에만 걸면 다른 경로로 읽을 때 구멍이 생기므로 큐브 단계에서 막는 구성입니다. 화면은 OpenUI5 표준 컨트롤만 쓰고 서비스 호출은 OData 로만 이루어집니다. 구체적인 권한 범위는 회사의 구매조직·플랜트 구조에 맞춰 설계해야 합니다.

B/L 과 문서가 아주 많아도 되나요?

집계를 DB 에서 하고, 입고 연월을 필수 조건으로 두고, 품목과 비용은 행을 눌렀을 때 읽는 구성이라 대용량을 염두에 두었습니다. 다만 실제 응답 시간은 고객사의 데이터 규모와 시스템에 달려 있어 이 글은 수치를 약속하지 않습니다. 운영 데이터로 측정한 뒤 인덱스와 조건을 조정하는 단계를 거치시길 권합니다.

점검 결과가 곧 회계·세무 판단입니까?

아닙니다. 이 화면은 분류·집계·대사를 돕는 점검 도구이며 최종 판단은 회사와 감사인이 합니다. 관세와 부가가치세 신고는 회사와 세무 대리인·관세사가 판단합니다. 화면은 ‘차이가 있다’, ‘포함된 것으로 보인다’ 까지만 알려 주고, 그 차이를 어떻게 처리할지는 정하지 않습니다.

샘플의 환율·관세율·거래처는 실제 값입니까?

아닙니다. 샘플 데이터의 환율과 관세율은 시연용 가정값이고 실제 고시값이 아닙니다. 거래처와 품목 이름도 일반 명칭으로 지은 가상의 자료이며 실제 거래와 관련이 없습니다. 화면 위쪽 안내 문구에도 같은 내용이 적혀 있습니다.

정정이나 취소가 있으면 어떻게 반영됩니까?

이 화면은 조회·점검 화면이라 원가를 확정하거나 전표를 만들지 않습니다. 운영 서비스에 연결했을 때 입고 취소나 송장 정정이 표준에서 이루어지면 그 결과가 원천 데이터에 반영되고, 이 화면은 다음 조회 때 바뀐 값으로 다시 계산합니다. 정정 처리 자체는 표준 T-code 에서 하시기 바랍니다.