파이썬 PyRFC로 SAP 사용하기 : 재고 확인 - MCHB Table

 

안녕하세요?


인터넷에 PyRFC를 이용하여 SAP를 이용하는 방법에 대한 예제 코드가 거의 전무하다시피하여, 일부 공유하고자 합니다. 저는 영업직이라 SAP에서 재고, 출하 내역, 판매 실적 확인 등의 일부 기능만 사용하고 SAP에 대한 이해도 깊지 못합니다. 제가 아는 선에서 설명하였으므로 혹시 잘못된 내용이 있으면 알려주세요.

 

 여기서는 파이썬을 이용하여 SAP R/3의 데이터 테이블에 접근합니다. GUI Scripting을 이용하는 것 보다 PyRFC를 이용하는 것이 훨씬 더 빠르고 편리합니다. 물론 처음 사용하는 게 좀 어렵고 까다롭지만요..

 

     

    1. 기본 정보

     1) SAP 테이블에 대하여

     SAP에서 Transaction을 하는 것은 기본적으로 SAP 데이터베이스의 테이블에 쿼리를 날려 데이터를 가지고 오는 것입니다. 예를 들어 SAP GUI에서 재고를 확인하는 T Code MMBE (Stock Overview) 는 SAP 테이블인 MCHB를 가져오는 것입니다.  (https://www.se80.co.uk/saptables/m/mchb/mchb.htm

    Fields on MCHB

     

    만약 아래와 같이 MMBE에서 Material No. 가 "50037259"이고, Plant가 KR1E 제품의 재고를 검색한 결과는, PyRFC에서 MATNR에 "50037259"를, WERKS에 "KR1E"를 넣고 조회한 것과 거의 동일합니다. (재고가 0인 것도 뜨는 등 정리되지 않은 Raw Data가 나옴)

    T Code MMBE

     

     

    SAP의 거의 모든 데이터는 테이블로 이루어져 있습니다. 위의 MCHB 에 사용되는 Field 중 하나인 MATNR(Material Number)도 MARA(General Material Data Table)에서 나온 것으로, 해당 필드를 Key로 사용하여 MCHB를 포함한 다른 테이블에서도 쿼리를 날립니다.

    Material Master Data 구조 (아래 PDF 파일에 있는 내용)

    SAP R/3의 데이터베이스가 전체적으로 어떻게 구성이 되어 있는지 보시려면 아래의 첨부 파일을 참조해주세요. 저는 PyRFC를 이용하면서 필요한 내용에 대해서는 그때그때 구글에 검색해서 사용했습니다.

    PFCLopezRuizAnnex3.pdf
    0.07MB

     

     

     

    SAP GUI에서 Table Name 및 Field Name 확인하는 법

    1) 입력창, 검색결과 상관없이 확인하고 싶은 Field를 클릭

    2) F1을 누름

    3) 새 창이 뜨면 Technical Information  클릭 (망치/스패너 아이콘)

    4) Techincal Information 창에서 Table Name과 Field Name 확인 가능

     

    예시)

    실적 화면에서 Sold-to (Customer Number) 를 확인하니, 해당 필드는 KNA1 테이블의 KUNNR 필드임을 알 수 있습니다. KNA1는 Customer Number (Sold to)를 고객사 이름으로 Mapping 할 때 주로 사용합니다. (https://www.se80.co.uk/saptables/k/kna1/kna1.htm)

     

     

     2) PyRFC에 대하여

     

    PyRFC는 SAP에서 사용하는 언어인 ABAP를 Python으로도 이용할 수 있도록 만들어진 패키지입니다. SAP에서는 RFC (Remote Function Call)이라고 하여 SAP 프로그램을 실행하지 않고 밖에서도 이용할 수 있는 툴을 제공하고 있습니다. (https://support.sap.com/en/product/connectors/nwrfcsdk.html). PyRFC는 해당 툴을 파이썬으로 이용할 수 있도록 해주고 있으며, SAP Github에서 직접 관리하고 있습니다. (https://github.com/SAP/PyRFC)

     

    단순히 검색 용도로만 사용하기에는 다소 어렵고 복잡하지만, SAP 관련 업무를 자동화하기에는 SAP GUI Scriping 보다 훨씬 빠르고 편리합니다. 예를 들어 제 경우에는 정기적으로 당월 출하실적 및 현재 재고를 파악하여 Forecast 대비해서 문제가 될 것 같은 내용에 대하여 정리하여 아웃룩으로 메일을 발송하는 데 사용하고 있습니다. SAP GUI에서 다른 기능을 사용하고 있거나, 실행하고 있지 않아도 상관없으며, GUI 로 검색하면 3분씩이나 걸릴 데이터도 RFC를 이용하면 몇초 안에 다 받을 수 있습니다.

     

    저는 회사 내에서 다른 개발자가 PyRFC를 더 편리하게 사용할 수 있도록 패키지를 만들어 주어 그것을 이용하고 있습니다만, 제가 처음에 많이 헤맸던 것 처럼 PyRFC 예제 코드를 찾아 헤매는 분들이 계실 것 같습니다. 그래서 간단한 것들은 제가 사용하는 패키지가 아니라 PyRFC를 바로 이용하는 코드를 작성하여 소개하고 공유하고자 합니다.

     

    저는 PyRFC를 이용하여 주로 재고, 실적 등의 조회 기능을 사용하고 있으며, SAP의 기능 중 Function Call (데이터 조회가 아닌 레포트 작성 등의 기능)은 제 업무에서 사용해본 적 없습니다.

     

     

     

     

    2. 준비물

     1) PyRFC 설치 

     

    기본적으로 아래의 PyRFC Github의 설명을 따라하면 됩니다.

     

     SAP NWRFC SDK의 다운로드를 위해서는 SAP partner 혹은 SAP Customer 계정이 필요하니, 회사의 SAP 담당자에게 문의하세요.

    https://github.com/SAP/PyRFC

     

    GitHub - SAP/PyRFC: Asynchronous, non-blocking SAP NW RFC SDK bindings for Python

    Asynchronous, non-blocking SAP NW RFC SDK bindings for Python - GitHub - SAP/PyRFC: Asynchronous, non-blocking SAP NW RFC SDK bindings for Python

    github.com

     

    정상적으로 설치되면, 파이썬에서 pyrfc를 import 할 수 있습니다.

    에러 없이 임포트

     

     2) Credentials 만들기

    SAP 접속에 필요한 아이디, 비밀번호 등의  정보를 미리 확인해 두어야 합니다. 저 같은 경우에는 json 파일로 저장하면 편리합니다. 아래는 제가 사용하는 credentials.json 파일입니다.

    credentials.json

     

     (1) ashost : 서버의 주소입니다. SAP GUI에서 상단에서 "System" -> "Status" 누르시면 뜨는 창에서 Other kernel info. -> 누르시면 System Information에 IP Address가 뜹니다. 해당 IP 주소가 ashost 입니다.

     

     (2) sysnr : 시스템 번호라는데 모르겠습니다. 저는 다른 사람들이 쓰는 숫자 그대로 따라서 11로 사용하고 있는데, 아마 Status 창에 뜨는 Host data에 Server name에 마지막 두자리 숫자가 아닐까 조심스레 추측해봅니다.

     (3) Client : Status 창에 뜹니다.

     (4) user, passwd : SAP 아이디, 비밀번호입니다.

     

     

    내용을 완성하여 json 형식으로 저장하면, 파이썬에서 아래와 같이 불러와 사용할 수 있습니다.

    f = open("credentials.json")
    credentials = json.load(f)

     

     

     

    3 . PyRFC 예시 코드 - MCHB :  Stock 확인

    편의상 Jupyter Notebook을 사용하겠습니다.

     

    MCHB Table (Batch Stocks Table) 에서 Plant가 "KR18"인 Item들의 Available Stock을 찾는 코드입니다. SAP에서 T Code MMBE와 유사합니다.

    import pyrfc
    import json
    
    f = open("C:\\Users\\KwonMi\\credentials.json")
    credentials = json.load(f)
    
    with pyrfc.Connection(**credentials) as conn:
        fields = ["WERKS" ,"MATNR" ,"CHARG" ,"LGORT" ,"CLABS"]
        result = conn.call("RFC_READ_TABLE", QUERY_TABLE='MCHB', FIELDS = fields,
                           OPTIONS = [{'TEXT': "WERKS = 'KR18'"}], DELIMITER = ",")
        
        print(result)

     - credentials은 json 파일 저장 위치를 불러오시면 됩니다.

     - fields는 총 5개를 선택하였으며, 각각 필드의 내용은 아래와 같습니다.

    • WERKS : Plant
    • MATNR : Material No.
    • CHARG : Batch No.
    • LGORT : Storage Location
    • CLABS : Available Stock

     더 많은 필드를 선택할 수 있으며, 구글에서 "SAP TABLE MCHB" 등으로 검색하면 나오는 싸이트를 참고하시거나, 혹은 SAP GUI에서 원하는 검색 후, 결과 값이 나오는 부분을 클릭하여 앞서 설명한 방법으로 Field Name을 확인해도 좋습니다.

     

    conn.call

    conn.call("RFC_READ_TABLE", QUERY_TABLE='MCHB', FIELDS = fields, OPTIONS = [{'TEXT': "WERKS = 'KR18'"}])

    직접적으로 쿼리를 수행하는 부분입니다.

     - RFC_READ_TABLE 이라는 모듈을 사용할것이고, 해당 모듈은 테이블을 읽어오는 기능을 가지고 있습니다.

     - QUERY_TABEL : 검색을 수행할 테이블은 "MCHB" 입니다.

     - FIELDS : 검색 결과에 표시할 필드는 fields에 있으며, 해당 내용은 위에서 설명하였습니다.

     - OPTION : 검색 조건입니다. 여기서는 "WERK" 이 'KR18'이어야 한다는 조건을 걸었습니다.

     - DELIMITER는 필드를 구분하기 위한 Delimiter 입니다. 아래에서 살펴보겠지만 쿼리 결과는 각 Field의 Length에 따라 구분 가능하므로 따로 입력하지 않는 것이 좋습니다. 여기서는 설명을 위하여 넣었습니다. 

     

    1) 실행 결과

     

    결과를 보니 Dictionary 타입의 값을 리턴하였으며, 키는 DATA, FIELDS, OPTIONS 입니다.

     

    (1) result["DATA"]

     

    위의 쿼리 결과에서 보듯 result["DATA"] 는 실제 얻고자 하는 재고 값의 딕셔너리의 리스트를 리턴했습니다. Delimiter로 구분 가능하며 각 딕셔너리의 값이 "Plant, Mat. No., Batch No., Storage Location, Available Stock"으로 이루어진 스트링입니다. 

     

     

    예를 들어 result["DATA"][0]["WA"] 의 값인 아래의 경우 결과의 해석은 아래와 같습니다.

    'KR18,000000000053536028,00007704N0,GITL,       0.000'

     - Plant : KR18

     - Mat. No. : 000000000053536028 => 필요에 따라 strip 함수를 이용하여 53536028로 수정하여 사용

     - Batch. No. : 00007704N0

     - Storage Location : GITL

     - Available Stock : 0.000

     

     

     위에서 잠깐 말했던 것처럼 재고가 0인 경우가 결과에 포함되고, 또한 SAP GUI 상에서 쿼리를 날릴 때 숨겨진 옵션 없이 순수하게 직접 입력한 조건을 가지고 테이블에 직접 접근하기 때문에 SAP GUI 상에서 검색한 것과는 데이터가 다릅니다만, 실제로 데이터를 다루고 정리하면 결국 값은 똑같다는 것을 알 수 있습니다.

     

    데이터를 정리하는 것은 여기서는 자세히 다루지 않겠습니다.

     

    (2) result["FIELDS"]

    FIELDS에 대한 정보입니다. 처음 쿼리 날릴 때 입력한 Field List이며, 각 필드에 대한 설명이 있습니다.

     

     

    설명을 위하여 위의 result["DATA"][0]["WA"] 값을 다시 가져 오겠습니다. 

    'KR18,000000000053536028,00007704N0,GITL,       0.000'

     

    - FIELDNAME : 이름 그대로 필드 이름입니다. 

    - OFFSET : 결과에서 각 필드가 위치한 곳의 Index입니다.

    - LENGTH : 결과에서 각 필드가 차지하는 크기(길이)입니다.

      -> 예를 들어 WERK는 Index 0에서 시작하고 길이가 4 이므로 결과 String에서 Index 0부터 3까지의 값입니다

      -> 마찬가지로 MATNR은 Index 5에서 시작하고 길이가 18이므로 Index 5부터 22까지의 값입니다.

      -> Index 4와 Index 23은 Delimter ','가 들어가는 자리입니다. 

      => 결과적으로, OFFSET과 LENGTH를 이용하여 결과값 String의 각 필드값을 구분할 수 있습니다. 

     

    - TYPE : 필드 값의 Type입니다. 자세한 내용은 아래 표 참조 

    - FIELDTEXT : 필드의 Description 입니다.

     

    https://github.com/SAP/PyRFC/blob/main/doc/tables/data_types.csv

     

    (3) result["OPTIONS"]

    쿼리를 날릴 때 입력한 조건입니다.

     

     

     

     2) 데이터 정리

     얻어진 데이터는 필요에 따라 정리하여 사용하시면 됩니다. 데이터 타입에 유의하세요..

     

     

    (예시)

    import pandas as pd
    
    data = []
    for line in result["DATA"]:
        raw_data = line["WA"].strip().split(delimiter)
        data.append(raw_data)
        
    pd.DataFrame(data)

     

     

     

     

    마치며

    회사에서 제공하는 모듈만 이용하다가 pyrfc를 직접 이용하려니 까다롭네요. 이 게시물에서는 간단히 재고를 파악하는 것만 살펴보았습니다만, SAP의 모든 테이블을 RFC를 통하여 읽어올 수 있습니다. 

     

    검색할 때 조건을 거는 것 (OPTIONS)에 대한 설명이 부족한 듯 하여, 기회가 되면 다음에는 다른 테이블을 이용하는 것과 여러 조건을 사용하는 것에 대해서 쓸 수 있도록 하겠습니다.

     

    질문을 주셔도 제대로 답변을 드릴 수 있을지 모르겠네요.

    읽어주셔서 감사합니다.

    댓글

    Designed by JB FACTORY