SAP接口编程 - PyRFC +Flask+Power Query 实现 SAP 系统科目余额表

得益于 Python 的简洁以及 PyRFC 的加持,SAP 接口编程变得非常简单。本篇介绍如何使用 PyRFC 和 Flask 提供 Restful 服务,程序要实现的目标为:在 Excel 中通过 Restful Service 连接到 SAP系统,在 Excel 中创建科目余额表,报表功能与 SAP 事务码 F.08 类似。选择 Python 而非 用 ABAP 实现 Restful 服务,优点之一是对 SAP 没有侵入性。

需要要用到两个函数:

  • BAPI_GL_ACC_GETLIST : 根据公司代码获取会计科目的清单
  • BAPI_GL_ACC_GETPERIODBALANCES: 获取会计科目在会计年度内各个月份的借方发生额、贷方发生额和余额,与 事务码 FAGLB03 类似

不熟悉两个函数用法的小伙伴,可以在 SAP 系统中用 SE37 来测试,了解函数的参数和返回值。

Restful API

新建一个项目,项目的文件结构如下:

首先,在 sap_system.py 文件中,使用一个 dict 存放连接到 SAP 系统的登录参数:

# 登录到SAP系统的参数
sap_conn_params = {
    "user": "stone",
    "passwd": "w123456",
    "ashost": "192.168.44.100",
    "sysnr": "00",
    "lang": "EN",
    "client": "001"
}

调用 SAP 函数的代码在 GL.py 文件中编写,PyRFC 自动管理 SAP 连接,不需要手动打开和关闭连接,但应该避免每个函数都创建一个连接对象,我将获取 SAP 连接的代码放在一个单独的函数中。

def get_sap_connection():
    logon_params = sap_system.sap_conn_params
    conn = pyrfc.Connection(**logon_params)

    return conn

调用 BAPI_GL_ACC_GETLIST 返回 科目清单的方法:

class SAPGL(object):
    def __init__(self) -> None:
        self.sap_connection = get_sap_connection()

    # OTHER CODES
        
    def get_gl_acc_list(self, cocd, lang):
        """
        获取会计科目清单
        """

        conn = self.sap_connection

        result = conn.call("BAPI_GL_ACC_GETLIST",
                           COMPANYCODE=cocd,
                           LANGUAGE=lang)
        return result['ACCOUNT_LIST']

调用 BAPI_GL_ACC_GETPERIODBALANCES 函数获取某一个会计科目的在某一年度的借方发生额、贷方发生额和余额:

class SAPGL(object):    
    def get_acc_balances(self, cocd, gl_account, fiscal_year):
        """
        获取会计科目在某一会计年度内按月份的发生额和余额
        """

        conn = self.sap_connection
        result = conn.call("BAPI_GL_ACC_GETPERIODBALANCES",
                           COMPANYCODE=cocd,
                           GLACCT=g_laccount,
                           FISCALYEAR=fiscal_year,
                           CURRENCYTYPE="10")
        return result['ACCOUNT_BALANCES'] 

结合这两个函数,获取所有会计科目的科目余额:

  def get_all_acc_balances(self, cocd, fiscal_year):
       """
       获取所有会计科目在某一会计年度内按月份的发生额和余额
       """

       # results for account balances
       gl_acc_balances = []

       # 获取所有会计科目
       accounts = self.get_gl_acc_list(cocd, '1') # 1表示简体中文

       # 遍历会计科目,获取每一个科目的发生额和余额
       for item in accounts:
           account = item.get('GL_ACCOUNT')
           balances_in_year = self.get_acc_balances(cocd, account, fiscal_year)

           for period_balance in balances_in_year:
               gl_acc_balances.append(period_balance)

       return gl_acc_balances

通过 Flask 提供三个 Web API:

# 会计科目列表
- /acclist/<cocd>

# 会计科目年度发生额和余额
- /accbal/<cocd>/<account>/<year>
- 
# 根据公司代码获取所有会计科目的发生额和余额
- /balances/<cocd>/<year>

代码很直观:

from flask import Flask, request, make_response, jsonify
from SAP.GL import SAPGL

app = Flask(__name__)

@app.route("/")
def index():
    return "index page"

@app.route("/accbal/<cocd>/<account>/<year>")
def get_acc_balances(cocd, account, year):   
    sap_gl = SAPGL();
    acc_balances = sap_gl.get_ac_balances(str.upper(cocd), account, year)

    return jsonify(acc_balances)

@app.route("/acclist/<cocd>")
def get_gl_acc_list(cocd):
    sap_gl = SAPGL();
    gl_list = sap_gl.get_gl_acc_list(str.upper(cocd), '1')

    return jsonify(gl_list)

@app.route('/balances/<cocd>/<year>')
def get_all_acc_balances(cocd, year):  
    sap_gl = SAPGL();
    balances = sap_gl.get_all_acc_balances(str.upper(cocd), year)
    return jsonify(balances)


if __name__ == "__main__":
    app.run()

Power Query 消费 Restful API

接下来,在 Excel 中通过消费这些 Restful Service,首先获取会计科目清单。对 Power Query 不熟悉的小伙伴请参考我之前写的 Power Query 系列。


Power Query 从网站获取的 json 格式数据,转换成表格基本都是下面要演示的几个步骤,首先将列表(List)转换为表:


然后点击表头的展开图标进行展开:

得到如下所示的结果:

高级编辑器中查看对应的脚本:


将查询命名为 acclist,acclist 的结果不需要上载到 Excel 工作表,仅仅保留在 Power Query 中(上载的时候选择仅连接)。

用同样的方法从 URL : http://127.0.0.1:5000/balances/z900/2020 将所有科目的发生额和余额导入到 Power Query 作为第二个查询,将查询命名为 accbalances。因为 python 对 account balances 用的 dict 数据类型,dict 是没有顺序的,所以导入到 Power Query 后字段的顺序并不符合我们的需要,需要在 Power Query 的界面中做调整,并且删除不需要的字段。完成后界面如下:

我们可以看到,会计科目的借方发生额、贷方发生额和余额都有,但没有期初余额。期初余额字段可以在 Power Query 中添加计算字段得到。然后再通过合并查询的功能,从查询 acclist 中关联的方式获得会计科目的描述:

合并查询得到的是一个 table 类型的结构化字段,通过展开操作,选择 LONG TEXT 字段。将完成的查询上载到 Excel 工作表。

查询 accbalances 上载到 Excel 的工作表包含一个会计年度的数据,为了方便查看,将期间字段设为切片器,这样就做好了一个方便查看任意月份的科目余额表。

源码

github - pyrfc

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了实现课程电商网站,我们可以使用Flask框架和MySQL数据库来构建网站,并使用PayPal API来处理付款。以下是一些步骤: 1. 首先,我们需要使用Flask和MySQL来构建网站。我们可以使用Flask的蓝图来组织我们的代,并使用MySQL来存储我们的数据。 2. 接下来,我们需要使用PayPal API来处理付款。我们可以使用PayPal的Vue.js包装组件vue-paypal-checkout来实现这一点。我们可以将这个组件添加到我们的网站中,并使用它来处理付款。 3. 我们还需要使用python-dotenv和flask-cli自定义命令来管理我们的环境变量和启动我们的应用程序。我们可以使用python-dotenv来加载我们的环境变量,并使用flask-cli自定义命令来启动我们的应用程序。 ```python # 示例代 from flask import Flask from flask_mysqldb import MySQL from paypalcheckoutsdk.core import PayPalHttpClient, SandboxEnvironment from paypalcheckoutsdk.orders import OrdersCreateRequest app = Flask(__name__) # 配置MySQL数据库 app.config['MYSQL_HOST'] = 'localhost' app.config['MYSQL_USER'] = 'root' app.config['MYSQL_PASSWORD'] = 'password' app.config['MYSQL_DB'] = 'mydatabase' mysql = MySQL(app) # 配置PayPal API client_id = 'YOUR_CLIENT_ID' client_secret = 'YOUR_CLIENT_SECRET' environment = SandboxEnvironment(client_id=client_id, client_secret=client_secret) client = PayPalHttpClient(environment) # 创建订单 request = OrdersCreateRequest() request.prefer('return=representation') request.request_body({ "intent": "CAPTURE", "purchase_units": [{ "amount": { "currency_code": "USD", "value": "100.00" } }] }) response = client.execute(request) print(response.result.id) # 自定义命令 @app.cli.command() def init_db(): cur = mysql.connection.cursor() cur.execute('CREATE TABLE IF NOT EXISTS courses (id INT, name VARCHAR(255), price FLOAT)') mysql.connection.commit() cur.close() print('Initialized the database.') # 蓝图 from flask import Blueprint bp = Blueprint('courses', __name__, url_prefix='/courses') @bp.route('/') def index(): cur = mysql.connection.cursor() cur.execute('SELECT * FROM courses') courses = cur.fetchall() cur.close() return render_template('courses/index.html', courses=courses) @bp.route('/<int:id>') def show(id): cur = mysql.connection.cursor() cur.execute('SELECT * FROM courses WHERE id = %s', [id]) course = cur.fetchone() cur.close() return render_template('courses/show.html', course=course) app.register_blueprint(bp) if __name__ == '__main__': app.run() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值