SAP

OBB8 기산일 증빙일 vs 전기일, 만기 갈린다 #shorts #SAP #ABAP

▶ YouTube에서 보기

1. 이 글이 답하는 질문

구매송장을 전기하면 SAP는 "언제까지 갚아야 하는지"와 "일찍 갚으면 얼마를 깎아주는지"를 자동으로 계산합니다. 이 계산의 출발점이 지급조건(Payment Terms)기산일(Baseline Date)입니다. 이 글은 SAP S/4HANA(온프레미스 2023 기준, ECC 6.0에서도 동일 로직)의 FI-AP 관점에서 만기일과 현금할인이 결정되는 구조를 단계별로 살펴봅니다.

  • 기산일이 어떤 규칙으로 채워지는지 설명할 수 있다
  • OBB8에서 2단계 할인 조건을 직접 구성할 수 있다
  • 전표의 BSEG-ZFBDT / ZBD1T / ZBD1P 필드가 어떻게 채워지는지 읽을 수 있다
  • 표준 함수모듈로 만기일을 프로그램에서 재계산할 수 있다

2. 미리 알아두면 좋은 배경

FB60(구매송장 입력)으로 전표를 한 번이라도 전기해 본 경험이 있으면 충분합니다. 전표 헤더(BKPF)와 라인아이템(BSEG)의 구분, 증빙일(BLDAT)과 전기일(BUDAT)의 차이 정도만 알고 있으면 됩니다. ABAP 예제가 나오지만 SELECT 문과 함수모듈 호출을 읽을 수 있는 수준이면 따라올 수 있습니다.

3. 테스트 환경과 사용한 버전

이 글의 예제는 다음 환경을 가정합니다.

  • 시스템: SAP S/4HANA 2023 온프레미스 (ECC 6.0 EHP8에서도 트랜잭션과 테이블 구조 동일)
  • 모듈: FI-AP (채무관리), 커스터마이징 권한 포함 개발/품질 서버
  • 주요 트랜잭션: OBB8(지급조건 정의), FB60(구매송장), FBL1N(공급업체 라인아이템 조회)
  • 주요 테이블: T052(지급조건 마스터), BSEG(전표 라인), LFB1(공급업체 회사코드 데이터)

실습 시나리오는 가상의 회사코드 3700(미르글로벌), 공급업체 500218(가온전자부품), 지급조건 M214를 사용합니다. 실제 시스템의 표준 조건(0001~0004 등)을 수정하지 말고 반드시 Z/사용자 네임스페이스로 새로 만드는 것이 권장됩니다.

4. 핵심 개념 — 기산일, 만기일, 현금할인의 3단 구조

지급조건을 "달리기 경주"에 비유하면 이해가 빠릅니다. 기산일은 출발선, 할인 기간은 보너스 구간, 순만기(Net Due Date)는 결승선입니다. 출발선이 어디냐에 따라 결승선 위치가 통째로 이동하기 때문에, 만기 계산에서 가장 먼저 확정해야 하는 것이 기산일입니다.

(1) 기산일(ZFBDT)의 결정 — OBB8의 Default for Baseline Date 설정이 네 가지 중 하나를 지정합니다.

옵션기산일로 복사되는 값일반적인 용도
Document Date증빙일(BLDAT)송장 발행일 기준 계약이 많은 구매채무
Posting Date전기일(BUDAT)내부 전기 시점 기준 관리
Entry Date입력일(CPUDT)드묾, 입력 지연 페널티 방지용
No Default사용자가 직접 입력수기 통제가 필요한 특수 거래

같은 송장이라도 증빙일이 8월 1일, 전기일이 8월 10일이면 기산일 옵션에 따라 만기가 9일이나 벌어집니다. 이것이 "기산일 기준에 따라 만기가 달라지는 구조"의 핵심입니다.

(2) 만기일 계산 — 기산일에 지급조건의 일수를 더합니다. 추가로 고정일(Fixed Day)추가 개월(Additional Months)을 지정하면 "익월 25일 지급" 같은 국내 상거래 관행도 표현할 수 있습니다.

(3) 현금할인 단계 — 최대 3단계(T052의 ZTAG1/ZPRZ1, ZTAG2/ZPRZ2, ZTAG3)를 정의합니다. 예를 들어 "14일 내 2%, 30일 순액"이면 1단계가 14일/2%, 2단계가 30일/0%입니다. 전기 시점에 이 값들이 라인아이템의 ZBD1T/ZBD1P/ZBD2T로 복사되며, 이후 지급 프로그램(F110)은 T052가 아니라 전표에 복사된 값을 봅니다. 즉 전기 후 OBB8을 바꿔도 기존 미결항목의 조건은 변하지 않습니다. 할인 기준금액(SKFBT)은 회사코드 설정에 따라 총액 기준 또는 세금 제외 기준으로 잡힙니다.

5. 실전 예제 3단계

1단계 — 지급조건 M214 정의와 전표 반영 확인

OBB8에서 새 조건 M214를 만듭니다: 계정유형은 Vendor 체크, 기산일 기본값은 Document Date, 1단계 2% / 14일, 2단계 0% / 30일. 저장하면 T052에 한 행이 생깁니다. 이후 FB60으로 공급업체 500218에 증빙일 2026-08-01, 금액 1,100,000원 송장을 전기하면 라인아이템은 다음처럼 채워집니다.

" 전기 결과를 BSEG에서 직접 확인
SELECT SINGLE zfbdt, zterm, zbd1t, zbd1p, zbd2t, skfbt
  FROM bseg
  INTO @DATA(ls_item)
  WHERE bukrs = '3700'
    AND belnr = @lv_belnr
    AND gjahr = '2026'
    AND koart = 'K'.   " Vendor 라인

" 기대값: ZFBDT=20260801(증빙일 복사), ZBD1T=14, ZBD1P=2.000,
"        ZBD2T=30 → 할인만기 8/15, 순만기 8/31

여기서 2026-08-15까지 지급하면 22,000원(부가세 포함 기준 시)을 할인받고, 늦어도 2026-08-31까지는 전액을 지급해야 합니다.

2단계 — 실무 시나리오: 만기 재계산 리포트 (에러 처리와 로깅)

FBL1N은 순만기를 보여주지만, 마감 전 검증 리포트에서 "할인 마지노선"까지 함께 뽑아야 하는 경우가 많습니다. 표준 함수모듈 DETERMINE_DUE_DATE가 지급조건 로직을 그대로 재현해 줍니다.

DATA ls_faede TYPE faede.

ls_faede-shkzg = 'H'.            " 대변(채무)
ls_faede-koart = 'K'.
ls_faede-zfbdt = '20260801'.     " 기산일
ls_faede-zbd1t = 14.             " 1단계 할인 일수
ls_faede-zbd2t = 30.             " 순만기 일수
ls_faede-rebzg = space.

CALL FUNCTION 'DETERMINE_DUE_DATE'
  CHANGING
    c_faede                    = ls_faede
  EXCEPTIONS
    account_type_not_supported = 1
    OTHERS                     = 2.

IF sy-subrc <> 0.
  " 애플리케이션 로그(BAL)에 남기고 해당 건은 건너뜀
  MESSAGE e001(zfi_ap) WITH lv_belnr INTO DATA(lv_msg).
  zcl_ap_log=>get( 'ZAP_DUE' )->add_msg( )->save( ).
  RETURN.
ENDIF.

" ls_faede-netdt = 순만기(8/31), ls_faede-sk1dt = 1단계 할인만기(8/15)
WRITE: / |순만기: { ls_faede-netdt DATE = USER }|,
       / |할인만기: { ls_faede-sk1dt DATE = USER }|.

기산일이 비어 있는 특수 전표(ZFBDT 초기값)가 섞여 들어오면 계산 결과가 왜곡되므로, 호출 전에 IF ls_faede-zfbdt IS INITIAL 가드를 두고 로그로 분리하는 것이 일반적입니다. 어음/선지급(특별 G/L) 라인은 만기 필드 의미가 다르므로 UMSKZ가 있는 라인은 별도 분기 처리합니다.

3단계 — 프로덕션: CDS 뷰 기반 할인 기회 모니터링

대량 미결항목을 매일 스캔한다면 ABAP 루프보다 CDS 뷰로 DB에 계산을 내리는 편이 성능상 유리합니다. S/4HANA에서는 BSEG 대신 미결항목이 정리된 소스에서 읽되, 여기서는 구조를 보여주기 위해 단순화했습니다.

@AbapCatalog.sqlViewName: 'ZAPDISCV'
@AccessControl.authorizationCheck: #CHECK  " DCL로 회사코드 권한 통제
define view Z_AP_Discount_Watch as select from bseg
  inner join bkpf on bkpf.bukrs = bseg.bukrs
                 and bkpf.belnr = bseg.belnr
                 and bkpf.gjahr = bseg.gjahr
{
  key bseg.bukrs,
  key bseg.belnr,
  key bseg.gjahr,
      bseg.lifnr,
      bseg.zfbdt,
      dats_add_days(bseg.zfbdt, cast(bseg.zbd1t as abap.int2),
                    'INITIAL') as CashDiscountDeadline,
      dats_add_days(bseg.zfbdt, cast(bseg.zbd2t as abap.int2),
                    'INITIAL') as NetDueDate,
      bseg.zbd1p as DiscountPercent,
      bseg.skfbt as DiscountBase
}
where bseg.koart = 'K'
  and bseg.augbl = ''     " 미결항목만
  and bseg.zbd1p > 0

운영 반영 시 체크리스트: 권한은 DCL로 회사코드 단위 통제(#CHECK), 단위 테스트는 ABAP Unit + CDS Test Double Framework로 기산일/할인일수 경계값(0일, 월말, 윤년 2/29)을 검증하고, 배치 실행 시 SELECT에 회사코드·회계연도 필터를 반드시 포함해 풀스캔을 피합니다. 할인 마지노선이 3일 이내로 임박한 건만 결재 라인에 알림을 보내면 조기지급 할인을 실무적으로 회수할 수 있습니다.

6. 자주 만나는 함정

Q1. OBB8에서 할인율을 바꿨는데 기존 송장의 할인이 그대로예요. 정상 동작입니다. 지급조건은 전기 시점에 전표로 복사되는 구조라서, 이미 전기된 미결항목은 FB02 등으로 라인아이템의 할인 필드를 직접 수정해야 반영됩니다.

Q2. 만기일이 예상보다 열흘 늦게 나옵니다. 십중팔구 기산일 기본값 문제입니다. 조건이 Posting Date 기준인데 담당자가 Document Date 기준으로 암산한 경우가 대표적입니다. BSEG-ZFBDT를 열어 실제 출발선을 먼저 확인하세요. Fixed Day/Additional Months가 설정된 조건이라면 기산일 자체가 "익월 특정일"로 치환된다는 점도 함께 봐야 합니다.

Q3. 공급업체 마스터에 지급조건을 넣었는데 MIRO에서는 다른 조건이 뜹니다. 구매송장은 구매조직 데이터(구매정보 내 지급조건)가, FI 직접 전기는 회사코드 데이터(LFB1-ZTERM)가 우선하는 구조입니다. 두 곳의 값이 다르면 채널에 따라 다른 조건이 제안됩니다.

Q4. F110에서 할인이 안 잡혀요. 지급 실행일이 이미 1단계 할인만기를 지났는지, 그리고 회사코드의 최대 할인 허용(Tolerance) 설정에서 할인 기한 경과 시 처리 규칙이 어떻게 잡혀 있는지 순서대로 확인하는 것이 일반적인 진단 순서입니다.

7. 이어서 보면 좋은 글

지급조건의 기본 구조를 이해했다면 다음 주제로 확장하는 것을 권장합니다. 할부 지급조건(OBB9)은 하나의 송장을 여러 만기로 자동 분할하는 기능이고, 일자 제한(Day Limit)은 송장 일자에 따라 같은 조건 키가 다른 규칙으로 갈라지는 고급 설정입니다. 이후 자동지급 프로그램(F110)에서 할인만기·순만기·다음 실행일이 상호작용하는 지급 시점 최적화 로직, 그리고 총액/순액 할인 회계처리(Gross vs Net Procedure) 차이로 이어가면 채무관리 흐름 전체가 연결됩니다.

8. 더 읽어볼 자료

댓글 0

아직 댓글이 없습니다.