자금 솔루션 · 반제 전기

반제전기 — 미결 항목을 좌우로 갈라 놓고 짝은 규칙과 AI 가 먼저 찾는다, 퍼블릭의 비동기 전기까지 한 화면에서

왼쪽에 채권, 오른쪽에 입금을 세워 고르는 즉시 차액을 세고, 자동 매핑이 금액·참조번호·합계·할인·단수로 짝을 먼저 찾아 줍니다. 규칙이 못 고른 나머지는 AI 가 적요 글을 읽고, 금액 검증은 서버가 다시 합니다. 시뮬레이션으로 전표를 먼저 만들어 본 뒤 비동기 SOAP 요청을 넣고 상태를 되물어 전표번호까지 받아 옵니다. 소개 영상과 실제 화면 11종, 그리고 CDS 코드까지 정리했습니다.

소개 영상블로그 목차 순서대로 · 자막 포함

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

한 줄 요약 — 미결 항목을 왼쪽 채권 · 오른쪽 입금 두 쪽으로 갈라 맞추고, 맞춘 결과를 시뮬레이션으로 전표까지 만들어 본 뒤 퍼블릭이 유일하게 열어 둔 비동기 SOAP 으로 전기해 요청번호로 결과를 확인합니다.

핵심 포인트

핵심 포인트고객이 얻는 것지금 방식이라면
좌우로 갈라 맞춥니다채권과 입금이 따로 서 있어 무엇을 무엇에 맞추는지 한눈에 보입니다. 쪽마다 건수와 합계가 머리에 뜹니다.한 표에 섞인 목록에서 차변·대변을 눈으로 가려 가며 찾습니다.
짝을 기계가 먼저 찾습니다금액·할당번호·참조번호·묶음 합계·현금할인·단수차이·부분입금 일곱 규칙이 묶음을 만들고, 신뢰도와 근거를 함께 보여 줍니다.입금 한 건마다 어느 청구를 턴 것인지 목록을 훑어 가며 손으로 찾습니다.
규칙이 못 고른 것은 AI 가 읽습니다참조 칸은 비었는데 적요 글에만 송장번호가 적힌 입금 같은 것들입니다. 금액 검증은 서버가 다시 합니다.단서가 글 안에만 있으면 자동 반제(F.13)는 그냥 지나치고, 결국 사람이 하나씩 읽습니다.
차액을 고르는 즉시 셉니다선택이 바뀔 때마다 차변·대변·차액이 다시 계산되고, 맞지 않으면 전기가 막힙니다.전기 버튼을 누르고 나서야 잔액이 맞지 않는다는 오류를 봅니다.
전표를 먼저 만들어 봅니다전기키·계정·금액까지 붙은 반제 전표를 시뮬레이션으로 확인한 뒤 전기합니다.전기해 보고 틀리면 되돌립니다.
비동기를 감추지 않습니다요청번호와 상태, 진행률, 처리 로그를 화면 안에서 봅니다. 전기 전이면 요청을 취소할 수 있습니다.요청은 보냈는데 결과를 몰라 담당자에게 묻거나 전표 조회를 반복합니다.
조회조건과 전표헤더를 한 세트로 저장합니다다음에 열 때 조건과 헤더가 채워진 채 조회까지 끝나 있습니다.매번 같은 조건과 같은 헤더를 손으로 다시 채웁니다.
되돌리는 길을 같은 화면에 둡니다반제전표 번호로 되돌리면 항목이 다시 미결이 되고 잔액 항목도 정리됩니다.다른 트랜잭션을 열어 전표번호를 찾아 넣습니다.

사례로 보는 효과

월말에 고객 입금 40건을 미결 청구 120건에 맞춰 터는 일을 생각해 보겠습니다. 한 표에 섞여 있으면 차대 칸을 눈으로 가려 가며 찾고, 금액이 맞는지는 계산기로 더해 봅니다. 두 쪽으로 갈라 두면 왼쪽 합계와 오른쪽 합계가 머리에 떠 있어 얼마를 더 골라야 맞는지 바로 보입니다. 차액이 남으면 전기 전에 빨갛게 서므로, 전기해 보고 되돌리는 일이 줄어듭니다.

전기 뒤에도 달라집니다. 퍼블릭에서는 전기 요청이 큐로 들어가 전표번호가 바로 나오지 않습니다. 모니터가 없으면 「보내긴 했는데 됐나?」 를 확인하려고 전표 조회를 반복하게 됩니다. 요청번호와 상태를 화면 안에 두면 그 반복이 사라집니다.

도입하면 달라지는 것

  • 맞추는 과정이 눈에 보입니다 — 두 쪽 합계와 차액이 선택할 때마다 다시 계산됩니다.
  • 전기 전에 막습니다 — 잔액 불일치 · 통화 혼재 · 이미 반제된 항목을 제안 단계에서 걸러 냅니다.
  • 전표를 먼저 봅니다 — 전기키와 계정까지 붙은 라인을 확인하고 전기합니다.
  • 결과를 기다리지 않아도 됩니다 — 요청번호로 되묻고, 끝나면 목록에서 반제된 항목이 빠집니다.
  • 같은 조건을 다시 채우지 않습니다 — 조회조건과 전표헤더를 한 세트로 저장합니다.
  • 되돌리는 길이 같은 화면에 있습니다 — 요청 취소와 반제 취소를 나눠 두었습니다.

이런 회사에 맞습니다

  • S/4HANA Cloud Public Edition 을 쓰면서 반제 전기를 Fiori 표준 앱 밖에서 다루고 싶은 회사
  • 고객 입금이나 공급업체 지급 건수가 많아 한 표에서 맞추기 어려운 회사
  • 현금할인 · 단수차이 · 환율차이 때문에 차액 처리가 잦은 회사
  • 부분반제를 자주 쓰는 회사 — 잔액 항목이 어떻게 생기는지 화면에서 확인할 수 있습니다
  • 회사코드가 여러 개이고 담당자마다 보는 조건이 정해져 있는 회사

실행 화면 — 두 쪽으로 갈라 맞추고 전기까지

아래 화면은 모두 앱을 실제로 띄워 찍은 것입니다. 그림을 누르면 크게 볼 수 있습니다.

한 화면, 두 쪽으로 갈라 보기

한 화면, 두 쪽으로 갈라 보기
한 화면, 두 쪽으로 갈라 보기 — 왼쪽은 채권(미결 청구·차변), 오른쪽은 입금(상계 대상·대변)입니다. 쪽마다 건수와 합계를 머리에 띄웁니다.

한 표에 섞어 두면 무엇과 무엇을 맞춰야 하는지 눈으로 좇기 어렵습니다. 계정유형을 공급업체로 바꾸면 왼쪽이 채무(미결 송장·대변), 오른쪽이 지급(차변)으로 좌우가 뒤집힙니다. 총계정원장이나 전체를 고르면 차변·대변으로 둡니다.

양쪽에서 골라 맞추기

양쪽에서 골라 맞추기
양쪽에서 골라 맞추기 — 채권 선택 − 입금 선택 = 차액. 맞지 않으면 그 자리에서 빨갛게 섭니다.

고르는 즉시 두 쪽 합계와 차액이 다시 계산됩니다. 잔액이 맞지 않는 상태로는 전기가 막히고, 차액계정을 지정하거나 부분반제를 켜야 넘어갑니다. 전기 전에 눈으로 확인하는 자리입니다.

자동 매핑 — 규칙이 먼저 짝을 찾습니다

자동 매핑 — 규칙이 먼저 짝을 찾습니다
자동 매핑 — 규칙이 먼저 짝을 찾습니다 — 정확일치 · 참조합계 · 금액일치 · 묶음합계 · 현금할인 · 단수차이 · 부분입금 — 일곱 규칙과 신뢰도, 그리고 근거 문장.

화면이 보고 있는 그 조회 결과로 짝을 찾습니다. 위에서 잡힌 항목은 아래 규칙이 다시 쓰지 않고, 한 항목은 한 묶음에만 들어갑니다. 묶음을 고르면 아래 표에 그 묶음에 든 항목이 좌/우 구분과 함께 펼쳐집니다. 그림의 G003 은 참조 AM1D0003 으로 묶인 청구 세 건(240만 + 310만 + 175만)이 입금 725만과 맞아떨어진 경우입니다.

AI 보강 — 규칙이 남긴 것만 모델이 읽습니다

AI 보강 — 규칙이 남긴 것만 모델이 읽습니다
AI 보강 — 규칙이 남긴 것만 모델이 읽습니다 — 참조번호 칸은 비어 있고 적요 글에만 송장번호가 적힌 입금 — 신뢰도 76%와 근거 문장이 함께 붙습니다.

필드만 보는 규칙으로는 잡히지 않는 항목이 남습니다. AI 보강은 그 나머지만 거래처별로 모아 모델에게 묻습니다. 모델은 어느 것끼리 한 짝인지만 고르고, 금액·합계·차액은 서버가 다시 계산합니다. 모델이 거래처를 넘나드는 짝을 고르면 검증에서 버립니다.

고른 묶음을 양쪽 표 선택으로

고른 묶음을 양쪽 표 선택으로
고른 묶음을 양쪽 표 선택으로 — 자동 매핑은 전기까지 하지 않습니다 — 고른 묶음만 선택으로 옮기고 차액사유까지 맞춰 둡니다.

차액이 남는 묶음(현금할인·단수차이·부분입금)이면 차액사유나 부분반제를 미리 켜 두어 이어지는 시뮬레이션에서 오류 라인이 서지 않게 합니다. 그다음은 지금까지와 똑같습니다.

시뮬레이션 — 반제 전표 미리보기

시뮬레이션 — 반제 전표 미리보기
시뮬레이션 — 반제 전표 미리보기 — 원 항목을 반대 차대로 터는 라인과 차액 라인을 전기키까지 붙여 만들어 보여 줍니다.

전기키는 고객 차변 01 · 대변 15, 공급업체 차변 21 · 대변 25, 총계정원장 차변 40 · 대변 50 으로 세웁니다. 라인 종류를 반제 · 차액 · 잔액 · 오류로 나눠 두어, 오류가 하나라도 있으면 전기 버튼이 막힙니다.

전표헤더 검증

전표헤더 검증
전표헤더 검증 — 회계기간 · 날짜 앞뒤 · 통화 · 환율 · 헤더텍스트 길이를 전기 전에 걸러 냅니다.

전기일이 열린 기간을 벗어났는지, 증빙일이 전기일보다 뒤인지, 외화인데 환율이 비었는지, 환율이 기준환율과 10% 넘게 벌어졌는지를 봅니다. 오류와 경고를 나눠 돌려주므로 경고는 알고 넘어갈 수 있습니다.

전기 모니터 — 비동기 요청

전기 모니터 — 비동기 요청
전기 모니터 — 비동기 요청 — 요청번호 · 상태 · 진행률 · 반제전표 · SOAP 오퍼레이션과 단계별 처리 로그.

전기 버튼을 누르면 전표번호가 아니라 요청번호가 돌아옵니다. 접수 → 큐 대기 → 전기 처리중 → 전기 완료까지 상태를 되물어 따라가고, 완료 시점에 반제전표 번호가 채워집니다. 전기가 끝나기 전이라면 요청을 취소할 수 있습니다.

레이아웃 저장

레이아웃 저장
레이아웃 저장 — 조회조건과 전표헤더를 한 세트로 저장합니다.

반제 전기는 「무엇을 모을지」 와 「어떤 헤더로 전기할지」 가 늘 짝입니다. 둘을 따로 저장하면 다음에 반쪽만 맞습니다. 기본으로 지정하고 자동 적용을 켜 두면 앱을 열 때 조건과 헤더가 채워진 채 조회까지 끝나 있습니다.

저장된 레이아웃

저장된 레이아웃
저장된 레이아웃 — 무엇을 저장했는지 한 줄 요약으로 적어 둡니다.

적용을 누르면 조회조건과 전표헤더가 함께 돌아옵니다. 표의 컬럼 표시 여부도 같이 담깁니다.

반제 취소

반제 취소
반제 취소 — 반제전표 번호로 되돌립니다 — SAP 의 FBRA 자리입니다.

그 전표로 반제된 항목이 모두 다시 미결이 되고, 부분반제로 생겼던 잔액 항목은 함께 지워집니다. 전기가 아직 끝나지 않은 요청이라면 모니터에서 요청 취소로 멈추는 편이 깔끔합니다.

자동 매핑과 AI — 짝을 찾는 일을 규칙과 모델에 나눠 맡기는 법

반제 화면에서 사람이 가장 오래 쓰는 시간은 전표를 만드는 시간이 아니라 「이 입금이 어느 청구를 턴 것인가」 를 찾는 시간입니다. 그 찾기는 대개 몇 가지 단서로 끝납니다 — 금액, 할당번호, 참조(송장)번호, 여러 건의 합, 약정 할인, 끝자리 단수. 자동 매핑은 그 단서를 규칙으로 적어 두고, 규칙이 못 고른 나머지만 모델에게 묻습니다.

규칙 일곱 가지

순서규칙무엇을 보나신뢰도차액 사유
①정확일치 EXACT금액이 같고 할당번호 또는 참조번호도 같다99%—
②참조합계 REFSUM같은 참조·할당번호로 묶인 여러 건의 합이 입금과 같다96%—
③금액일치 AMOUNT단서는 없지만 금액이 딱 같다90%—
④묶음합계 SUMN입금 한 건이 청구 2~4건의 합이다 (부분집합 탐색)86%—
⑤현금할인 DISCOUNT참조가 같고 차이가 약정 할인율 범위(0.3~3.5%)78%01 현금할인
⑥단수차이 ROUND차이가 허용 단수 안 (기본 원화 1,000원)74%02 단수차이
⑦부분입금 PARTIAL참조는 같고 금액은 일부만 들어왔다68%05 잔액 유지
⑧AI 추정규칙이 남긴 항목 — 적요 글에 적힌 송장번호·분할 표현 등40~92%검증 결과에 따라

위에서 잡힌 항목은 아래 규칙이 다시 쓰지 않습니다. 큰 금액부터 보고, 한 항목은 한 묶음에만 들어갑니다. 그리고 참조·할당번호라는 단서가 없는 근접 금액은 짝으로 보지 않습니다 — 금액이 비슷하다는 것만으로 묶으면 무작위로 가까운 금액이 잡혀 오탐이 납니다. 단서 없이 인정하는 것은 끝자리 차이뿐이고, 비율로 넓힌 창은 참조가 같을 때만 씁니다.

모델에게 맡기는 것과 맡기지 않는 것

모델은 짝만 고르고, 금액은 서버가 셉니다 — 모델은 금액을 지어낼 수 있고, 지어낸 금액은 원장과 맞지 않습니다. 그래서 모델에게는 「이 중에서 어느 것끼리 한 짝인지 고르고 이유를 적어라」 만 시키고, 합계·차액·잔액 일치는 모두 서버가 다시 계산합니다.
구분내용
질의 범위거래처(계정)별로 나눠 묻습니다. 섞어 보내면 거래처를 넘나드는 짝이 나오고, 그 짝은 검증에서 버려집니다. 기본은 계정 3곳 · 입금 10건 · 청구 16건까지.
후보 고르기적요에 송장·전표번호 같은 토큰이나 「분할·선결제·잔액·할인」 같은 낱말이 있는 입금부터 보냅니다. 남은 것을 전부 보내면 느리고 모델도 헷갈립니다.
응답 검증① 번호가 실제 항목을 가리키는가 ② 계정·통화가 같은가 ③ 입금이 청구보다 30% 넘게 크지 않은가. 덜 들어온 것(부분입금)은 금액이 벌어져도 받아들이고 잔액 사유를 붙입니다.
신뢰도 보정금액이 정확히 맞으면 올리고(최대 92%), 차이가 크면 내립니다(최소 40%). 모델이 스스로 적은 신뢰도는 88%를 넘지 못하게 묶어 둡니다.
모델이 없을 때설정 파일의 enabled 가 false 이거나 응답이 없으면 규칙 결과만 쓰고 그 사실을 화면 띠에 적습니다. 매핑이 안 되는 것보다 덜 똑똑한 매핑이 낫습니다.
API 키서비스는 키를 다루지 않습니다. 사내 게이트웨이가 키를 들고 있고, 설정 파일은 웹에서 읽히므로 키를 적지 않습니다.

실제로 무엇이 잡혔나

거래처 한 곳(미결 청구 21건 · 입금 13건)에서 규칙이 묶음 8개 19건을 8밀리초 만에 찾았습니다 — 정확일치 2 · 참조합계 1 · 금액일치 1 · 묶음합계 1 · 현금할인 1 · 단수차이 1 · 부분입금 1, 오탐 0건입니다. 남은 15건을 모델에 넘기자 참조 칸은 비어 있고 적요에만 「INV-…-10008 건 1차 분할」 이라고 적힌 입금 한 건을 950만원 청구의 분할 입금으로 집어냈습니다(신뢰도 76%, 18초). 같은 질의에서 모델이 고른 다른 짝 두 개는 거래처가 다르거나 금액이 맞지 않아 서버 검증에서 걸러졌습니다.

자동이라는 말의 경계

자동 매핑은 전기까지 하지 않습니다. 사람이 고른 묶음만 왼쪽·오른쪽 표의 선택으로 옮기고, 차액이 남는 묶음이면 차액사유나 부분반제를 미리 맞춰 둡니다. 그다음은 지금까지와 똑같이 시뮬레이션을 거쳐 전기합니다. 신뢰도와 근거 문장을 묶음마다 붙여 보여 주는 것도 같은 이유입니다 — 기계는 후보를 좁히는 데까지, 고르는 일은 사람이 합니다.

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

표준 기능내용이 화면에서
F-32 · F-44 · F-03고객 · 공급업체 · 총계정원장 미결 항목 반제계정유형만 바꾸면 같은 화면이 세 트랜잭션의 자리를 모두 맡습니다. 좌우 제목도 채권/입금 · 채무/지급 · 차변/대변으로 따라 바뀝니다.
F.13 · OB74자동 반제 (Automatic Clearing)표준 자동 반제는 OB74 에 정한 기준 필드(할당번호·참조번호 등)가 같고 잔액이 0 인 묶음만 텁니다. 이 화면의 자동 매핑은 그 기준을 일곱 규칙으로 넓혀 현금할인·단수차이·부분입금까지 묶고, 바로 전기하는 대신 신뢰도와 근거를 붙여 사람에게 고르게 합니다.
FB03전표 조회전기가 끝나면 받은 반제전표 번호로 원 전표를 확인합니다. 모니터의 전표번호가 그 번호입니다.
FBRA반제 취소반제 취소가 같은 자리를 맡습니다. 부분반제로 생긴 잔액 항목까지 함께 정리합니다.
FBL5N · FBL1N · FBL3N미결 항목 목록조회 결과 표가 같은 자료를 봅니다. 다만 목록만 보는 것이 아니라 그 자리에서 골라 전기까지 이어집니다.
OB09 · 차액 계정 설정차액 처리 계정차액사유를 고르면 그에 맞는 계정이 따라오도록 화면에 끌어왔습니다. 현금할인은 매출할인, 단수차이는 잡손실, 환율차이는 외환차손으로 기본 연결했습니다.
비동기 SOAPClearingAccountingDocumentCreateRequest_InS/4HANA Cloud Public Edition 이 반제 전기에 열어 둔 유일한 길입니다. 동기 OData 가 없어 요청번호로 되묻는 구조가 필요합니다.
퍼블릭 클라우드의 제약을 감추지 않았습니다 — S/4HANA Cloud Public Edition 은 반제 전기를 동기 OData 로 열어 주지 않습니다. 그래서 전기 버튼은 전표번호가 아니라 요청번호 를 돌려줍니다. 이 사실을 화면 뒤로 숨기면 사용자는 결과를 확인할 방법을 잃습니다. 요청번호 · 상태 · 진행률 · 처리 로그를 화면 안으로 끌어들인 이유입니다.

CDS 구성 — 운영 데이터로 갈 때의 뷰 레이어와 코드

데모는 JSON 기반 서비스로 동작하지만, 운영에서는 아래 뷰를 만들어 OData 로 노출하면 화면은 그대로 돕니다.

ZI_ClearingOpenItem

미결 항목 조회 뷰 — 화면 왼쪽·오른쪽 두 쪽을 모두 이 뷰 하나로 읽는다

@AbapCatalog.sqlViewName: 'ZICLROPEN'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '반제 대상 미결 항목'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT
define view ZI_ClearingOpenItem
  as select from I_OperationalAcctgDocItem as Item
  inner join   I_AccountingDocumentHeader  as Head
    on  Item.CompanyCode       = Head.CompanyCode
    and Item.AccountingDocument = Head.AccountingDocument
    and Item.FiscalYear        = Head.FiscalYear
{
  key Item.CompanyCode                                    as Bukrs,
  key Item.AccountingDocument                             as Belnr,
  key Item.FiscalYear                                     as Gjahr,
  key Item.AccountingDocumentItem                         as Buzei,

      // 계정유형 — 고객 D · 공급업체 K · 총계정원장 S
      case when Item.Customer <> '' then 'D'
           when Item.Supplier <> '' then 'K'
           else 'S' end                                   as Koart,
      case when Item.Customer <> '' then Item.Customer
           when Item.Supplier <> '' then Item.Supplier
           else Item.GLAccount end                        as Konto,
      Item.GLAccount                                      as Hkont,
      Head.AccountingDocumentType                         as Blart,
      Head.DocumentDate                                   as Bldat,
      Item.PostingDate                                    as Budat,
      Item.NetDueDate                                     as Netdt,
      Item.BaselineDate                                   as Zfbdt,
      Item.TransactionCurrency                            as Waers,
      Item.AmountInTransactionCurrency                    as Wrbtr,
      Item.AmountInCompanyCodeCurrency                    as Dmbtr,
      Item.DebitCreditCode                                as Shkzg,
      Item.DocumentItemText                               as Sgtxt,
      Item.AssignmentReference                            as Zuonr,
      Head.DocumentReferenceID                            as Xblnr,
      Item.PaymentTerms                                   as Zterm,
      Item.SpecialGLCode                                  as Umskz,
      Item.TaxCode                                        as Mwskz,
      Item.CostCenter                                     as Kostl,
      Item.ProfitCenter                                   as Prctr,
      Item.ClearingAccountingDocument                     as Augbl,
      Item.ClearingDate                                   as Augdt,

      // 미결 O · 반제 C — 화면의 "미결만" 조건이 이 칸을 본다
      case when Item.ClearingDate is initial then 'O' else 'C' end as Status,

      // 연체일 — 만기일이 지난 날 수(미결일 때만 센다)
      case when Item.ClearingDate is initial
                 and Item.NetDueDate < $session.system_date
           then dats_days_between( Item.NetDueDate, $session.system_date )
           else 0 end                                     as OverdueDays
}
where Item.FinancialAccountType <> ''

ZC_ClearingOpenItem

화면이 직접 부르는 소비 뷰 — 조회조건을 파라미터로 받는다

@AbapCatalog.sqlViewName: 'ZCCLROPEN'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '반제전기 — 미결 항목 조회'
@VDM.viewType: #CONSUMPTION
@OData.publish: true
@UI.headerInfo: { typeName: '미결 항목', typeNamePlural: '미결 항목' }
define view ZC_ClearingOpenItem
  with parameters
    @Environment.systemField: #SYSTEM_DATE
    p_KeyDate   : vdm_v_key_date,
    p_OnlyOpen  : abap_boolean,
    p_Overdue   : abap_boolean
  as select from ZI_ClearingOpenItem
{
  @UI.lineItem: [{ position: 10, label: '회사코드' }]
  key Bukrs,
  @UI.lineItem: [{ position: 20, label: '전표번호' }]
  key Belnr,
  key Gjahr,
  key Buzei,
      @UI.selectionField: [{ position: 10 }]
      Koart,
      @UI.selectionField: [{ position: 20 }]
      Konto,
      Hkont, Blart, Bldat, Budat, Netdt, Zfbdt,
      @UI.selectionField: [{ position: 30 }]
      Waers,
      @Semantics.amount.currencyCode: 'Waers'
      Wrbtr,
      @Semantics.amount.currencyCode: 'Waers'
      Dmbtr,
      Shkzg, Sgtxt, Zuonr, Xblnr, Zterm, Umskz, Mwskz, Kostl, Prctr,
      Augbl, Augdt, Status, OverdueDays
}
where ( :p_OnlyOpen = '' or Status  = 'O' )
  and ( :p_Overdue  = '' or OverdueDays > 0 )
  and Budat <= :p_KeyDate

ZI_ClearingRequest

비동기 전기 요청을 담는 테이블과 뷰 — 퍼블릭에서는 이 자리가 반드시 필요하다

// ── 테이블 ZFI_CLR_REQ ─────────────────────────────────────────────
// request_id  CHAR32   요청번호 (키)
// bukrs       BUKRS    회사코드
// status      CHAR12   ACCEPTED · QUEUED · INPROCESS · POSTED · FAILED · CANCELLED
// soap_msgid  CHAR64   SOAP 메시지 ID — 상태를 되물을 때 쓴다
// belnr       BELNR_D  전기된 반제전표 (완료 뒤 채워진다)
// gjahr       GJAHR
// msgty       CHAR1    메시지 유형
// message     CHAR220
// created_at  TIMESTAMPL
// updated_at  TIMESTAMPL
// 이 테이블이 있어야 "요청은 보냈는데 결과를 모르는" 구간이 사라진다.

@AbapCatalog.sqlViewName: 'ZICLRREQ'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '반제 전기 요청'
define view ZI_ClearingRequest
  as select from zfi_clr_req as Req
  left outer join I_AccountingDocumentHeader as Doc
    on  Req.bukrs = Doc.CompanyCode
    and Req.belnr = Doc.AccountingDocument
    and Req.gjahr = Doc.FiscalYear
{
  key Req.request_id                                      as RequestId,
      Req.bukrs                                           as Bukrs,
      Req.status                                          as Status,
      case Req.status
        when 'ACCEPTED'  then '요청 접수'
        when 'QUEUED'    then '큐 대기'
        when 'INPROCESS' then '전기 처리중'
        when 'POSTED'    then '전기 완료'
        when 'FAILED'    then '전기 실패'
        when 'CANCELLED' then '취소됨'
        else Req.status end                               as StatusText,
      Req.soap_msgid                                      as SoapMessageId,
      Req.belnr                                           as Belnr,
      Req.gjahr                                           as Gjahr,
      Doc.PostingDate                                     as Budat,
      Req.msgty                                           as MsgType,
      Req.message                                         as Message,
      Req.created_at                                      as CreatedAt,
      Req.updated_at                                      as UpdatedAt
}

운영 적용 시 해야 할 작업

단계내용
① 조회 뷰 두 벌ZI_ 기본 뷰와 ZC_ 소비 뷰를 만들고 OData 로 노출합니다. 화면의 조회조건 11가지를 파라미터와 $filter 로 받습니다.
② 좌우 구분은 뷰가 아니라 화면에서차대구분(Shkzg)은 뷰에서 그대로 내려 주고, 어느 쪽에 세울지는 화면이 계정유형을 보고 정합니다. 뷰를 둘로 나누면 합계를 맞출 때 두 번 읽게 됩니다.
③ 요청 테이블 한 벌비동기 전기는 요청번호와 상태를 담을 자리가 반드시 필요합니다. 위 ZFI_CLR_REQ 가 그 자리입니다.
④ SOAP 연결ClearingAccountingDocumentCreateRequest_In 으로 보내고, 응답의 메시지 ID 를 요청 테이블에 적습니다. 상태 조회는 Message Monitoring 또는 완료 알림(Confirmation) 으로 받습니다.
⑤ 폴링 주기큐 처리 주기에 맞춰 정합니다. 이 앱은 1.2초로 두었지만, 운영에서는 3~5초가 보통입니다.
⑥ 권한회사코드·계정유형 단위로 나누고, 반제 취소는 별도 권한으로 떼어 두는 편이 안전합니다.
⑦ 레이아웃 저장사용자별 테이블 한 벌이면 충분합니다. 조회조건과 전표헤더를 각각 JSON 문자열로 담으면 칸을 늘릴 때 테이블을 바꾸지 않아도 됩니다.

자주 묻는 질문 — 화면과 조작, 회계 처리, 도입과 운영

왜 왼쪽과 오른쪽으로 나눴나요?

반제는 결국 양쪽을 같은 금액으로 맞추는 일입니다. 한 표에 섞어 두면 차변인지 대변인지 칸을 보며 눈으로 가려야 해서, 건수가 늘어날수록 맞추기가 어려워집니다. 왼쪽에 채권, 오른쪽에 입금을 세워 두면 각 쪽의 합계가 머리에 떠 있어 얼마를 더 골라야 맞는지 바로 보입니다.

공급업체는 반대 아닌가요?

맞습니다. 고객은 청구가 차변, 입금이 대변이지만 공급업체는 송장이 대변, 지급이 차변입니다. 그래서 계정유형을 공급업체로 바꾸면 왼쪽이 채무(미결 송장·대변), 오른쪽이 지급(차변)으로 좌우 기준이 뒤집힙니다.

전기 버튼을 눌렀는데 왜 전표번호가 바로 안 나오나요?

SAP S/4HANA Cloud Public Edition 이 반제 전기를 동기 OData 로 열어 주지 않기 때문입니다. 열려 있는 길은 비동기 SOAP 하나여서 요청을 넣으면 요청번호만 돌아옵니다. 전표번호는 큐가 처리된 뒤 상태 조회로 받습니다. 전기 모니터가 그 되묻기를 대신합니다.

동기 전기는 아예 불가능한가요?

퍼블릭 에디션에서는 공개된 동기 API 가 없습니다. 온프레미스나 프라이빗 클라우드라면 BAPI_ACC_DOCUMENT_POST 로 동기 전기가 가능하므로, 이 화면에서 전기 호출 한 군데만 바꿔 끼우면 됩니다. 화면 구조는 그대로 씁니다.

자동 매핑은 F.13 자동 반제와 무엇이 다른가요?

표준 F.13 은 OB74 에 정해 둔 기준 필드가 같고 잔액이 정확히 0 인 묶음만 자동으로 텁니다. 기준이 엄격해 안전한 대신, 현금할인으로 2% 덜 들어온 입금이나 끝자리만 다른 입금, 적요에만 송장번호가 적힌 입금은 그냥 남습니다. 이 화면의 자동 매핑은 그 나머지를 일곱 규칙과 AI 로 더 집어 올리되, 전기까지 혼자 하지 않고 신뢰도와 근거를 붙여 사람에게 고르게 합니다. 바꿔 말하면 F.13 이 털고 남긴 자리를 메우는 도구입니다.

자동 매핑은 어떤 순서로 짝을 찾나요?

신뢰도가 높은 규칙부터 차례로 봅니다. ① 금액과 참조·할당번호가 모두 같음(99%) ② 같은 참조로 묶인 여러 건의 합이 입금과 같음(96%) ③ 금액만 같음(90%) ④ 입금 한 건이 청구 2~4건의 합(86%) ⑤ 참조가 같고 차이가 할인율 범위 0.3~3.5%(78%, 현금할인) ⑥ 차이가 허용 단수 안, 기본 1,000원(74%, 단수차이) ⑦ 참조는 같고 금액이 일부만 들어옴(68%, 부분입금). 위에서 잡힌 항목은 아래 규칙이 다시 쓰지 않고, 큰 금액부터 봅니다.

금액이 비슷하다는 이유만으로 묶으면 오탐이 나지 않나요?

그래서 참조·할당번호라는 단서가 없는 근접 금액은 규칙이 짝으로 보지 않습니다. 단서 없이 인정하는 것은 끝자리 차이(허용 단수 안)뿐이고, 비율로 넓힌 창은 참조가 같을 때만 씁니다. 이 조임을 넣기 전에는 무작위로 가까운 금액끼리 묶여 오탐이 났고, 넣은 뒤 같은 자료에서 오탐이 0건이 되었습니다.

AI 는 정확히 무엇을 하나요?

규칙이 짝을 찾지 못한 항목만 거래처별로 모아 모델에게 넘기고, 모델은 「어느 것끼리 한 짝인가」 와 그 이유 한 문장만 돌려줍니다. 금액·합계·차액·잔액 일치는 모두 서버가 다시 계산합니다. 모델은 금액을 지어낼 수 있고 지어낸 금액은 원장과 맞지 않기 때문입니다. 모델이 고른 짝도 번호가 실제 항목을 가리키는지, 계정·통화가 같은지, 입금이 청구보다 30% 넘게 크지 않은지를 서버가 검증한 뒤에야 화면에 오릅니다.

AI 에 어떤 자료가 나가나요? 꺼 둘 수 있나요?

규칙이 남긴 항목의 금액·만기일·할당번호·참조번호·적요뿐입니다. 거래처별로 입금 10건·청구 16건, 계정 3곳까지만 보냅니다. 모델 키는 서비스가 들고 있지 않고 게이트웨이가 보관하며, 연결 설정은 ai.json 한 파일로 바꿉니다. 그 파일의 enabled 를 false 로 두면 모델을 전혀 부르지 않고 규칙 결과만 씁니다. 자동 매핑이 두 단계(규칙 → AI 보강)로 나뉘어 있어 모델이 없어도 매핑 자체는 늘 동작합니다.

자동 매핑이 바로 전기까지 하나요?

하지 않습니다. 고른 묶음을 왼쪽·오른쪽 표의 선택으로 옮겨 줄 뿐이고, 그다음은 지금까지와 똑같이 시뮬레이션을 거쳐 사람이 전기합니다. 차액이 남는 묶음이면 차액사유(현금할인·단수차이)나 부분반제를 미리 맞춰 둡니다. 자동이라는 말이 「묻지 않고 전기한다」 는 뜻이 되지 않도록 한 칸을 비워 둔 것입니다.

차액이 남으면 어떻게 되나요?

그대로는 전기를 막습니다. 차액계정을 지정하면 그 계정으로 차액을 털고, 부분반제를 켜면 잔액만큼 새 미결 항목을 만듭니다. 둘 다 아니면 시뮬레이션에 「오류」 라인이 서고 전기 버튼이 막힙니다.

부분반제로 만들어진 잔액 항목은 어떻게 생기나요?

원 항목과 같은 계정·거래처로, 반제전표 번호에 라인 900 을 붙여 새 미결 항목이 생깁니다. SAP 의 Residual Item 과 같은 자리입니다. 나중에 반제를 취소하면 이 잔액 항목은 함께 지워집니다.

통화가 다른 항목을 같이 반제할 수 있나요?

막아 두었습니다. 한 반제 전표 안에서는 한 통화만 다룹니다. 회사코드도 마찬가지입니다. 섞어서 고르면 제안 단계에서 바로 알려 줍니다.

외화 항목은 어떻게 처리하나요?

통화가 현지통화와 다르면 환율 칸이 열립니다. 비어 있으면 검증에서 막고, 기준환율과 10% 넘게 벌어지면 경고합니다. 시뮬레이션의 현지통화 금액은 입력한 환율로 환산합니다.

레이아웃에는 정확히 무엇이 저장되나요?

조회조건(회사코드·계정유형·계정·통화·기간·만기·전표번호·할당번호·최소금액·미결만·연체만)과 전표헤더(전기일·증빙일·전표유형·통화·환율·헤더텍스트·참조·차액계정·차액사유·부분반제·전기방식), 자동 매핑 설정(허용 단수·묶음 최대 건수·만기일 창·신뢰도 하한), 그리고 표의 컬럼 표시 여부가 한 레코드에 같이 담깁니다.

기본 레이아웃은 어떻게 동작하나요?

저장할 때 「기본 레이아웃」 과 「앱을 열 때 자동으로 적용」 을 켜면, 다음에 앱을 열 때 그 조건과 헤더가 채워진 채 조회까지 끝나 있습니다. 기본은 하나만 둘 수 있고, 새로 지정하면 이전 기본은 풀립니다.

전기를 잘못 보냈습니다. 멈출 수 있나요?

전기가 끝나기 전이라면 모니터에서 요청 취소를 누르면 멈춥니다. 이미 전기가 끝났다면 반제 취소로 되돌립니다. 둘은 다른 일이라 버튼도 따로 두었습니다.

처리 로그에는 무엇이 남나요?

SOAP 요청을 큐에 넣은 시각과 오퍼레이션 이름, 대상 항목 수와 통화·전기일, 단계가 바뀔 때마다의 기록, 그리고 완료 또는 실패 메시지가 시간순으로 남습니다. 동기 방식을 골랐다면 퍼블릭에서는 동기가 열려 있지 않다는 경고도 함께 남습니다.

조회는 몇 건까지 되나요?

한 번에 500건까지 내려받고, 전체 건수는 따로 돌려줍니다. 화면 표는 sap.ui.table 이라 스크롤이 끊기지 않습니다. 더 좁히려면 만기일 이내나 최소금액 조건을 쓰는 편이 빠릅니다.

CSV 로 내려받으면 한글이 깨지지 않나요?

UTF-8 BOM 을 붙여 내보내므로 엑셀에서 그대로 열립니다. 좌우 두 쪽을 합친 목록이 한 파일로 나옵니다.

실제 SAP 에 붙이려면 무엇을 바꾸나요?

조회는 아래 CDS 절의 뷰 두 벌을 만들어 OData 로 노출하고, 전기는 비동기 SOAP 에 연결한 뒤 요청번호와 상태를 담을 테이블 한 벌을 두면 됩니다. 화면은 서비스 주소만 바꾸면 그대로 돕니다.

데이터가 실제 고객 값인가요?

아닙니다. 회사코드·거래처·계정·금액·환율은 모두 설명용으로 만든 가정값입니다. 반제가 필요한 상황을 보여 주려고 차액이 남는 조합도 일부러 섞어 두었습니다.