python实现GetExchangeRate获取汇率,C#改写python例子原创
金蝶云社区-空鹅机
空鹅机
84人赞赏了该文章 416次浏览 未经作者许可,禁止转载编辑于2024年09月20日 08:43:24
summary-icon摘要由AI智能服务提供

文本概述: 本文描述了在实现汇率获取功能时,对现有方法(C#)的修改和转为Python的过程。作者解释了需要自定义获取二开外汇卖出价汇率的原因,并展示了通过修改SQL查询(使用StringBuilder拼接)来获取汇率的过程。该SQL查询从T_BD_RATE数据表中获取直接汇率或间接汇率,并通过UNION合并两个查询结果。同时,还展示了如何在Python中准备SQL查询参数(使用List[SqlParam]),执行查询,并处理查询结果。最后,给出了Python实现的完整代码示例,包括必要的库引用和函数定义。

当我在实现汇率时,本来可以直接引用

 Kingdee.K3.FIN.App.Core中

CommonFunction的 

GetExchangeRate(Context ctx, long iCurrencyFromID, long iCurrencyToID, long iRateTypeID, DateTime RateDate)

或是

GetExchangeBusRate(Context ctx, long iCurrencyFromID, long iCurrencyToID, long iRateTypeID, DateTime RateDate)

获取直接汇率 


但是我要取一个二开的的外汇卖出价汇率

于是,自己修改了一下他的方法

(主要大头还是把C#转写为python的练习)


参数解释:

Context ctx 上下文 

long iCurrencyFromID 目标币别

long iCurrencyToID 本位币别 

long iRateTypeID 汇率类型(即期汇率、固定汇率等)

DateTime RateDate 取这个日期的汇率


image.png

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine(string.Format(" select FExchangeRate,FNo=1 from {0} ", "T_BD_RATE"));
stringBuilder.AppendLine(" where FForbidderID=0 and FRateTypeID=@RateTypeID ");
stringBuilder.AppendLine(" and FCYForID=@CyForID and FCYToID=@CyToID ");
stringBuilder.AppendLine(" and FBegDate <= @BegDate and FEndDate >= @EndDate and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ");
stringBuilder.AppendLine(" Union ");
stringBuilder.AppendLine(string.Format(" select FExchangeRate=FREVERSEEXRATE,FNo=2 from {0} ", "T_BD_RATE"));
stringBuilder.AppendLine(" where FForbidderID=0 and FRateTypeID=@RateTypeID ");
stringBuilder.AppendLine(" and FCYForID=@CyToID and FCYToID=@CyForID ");
stringBuilder.AppendLine(" and FBegDate <= @BegDate and FEndDate >= @EndDate and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ");
stringBuilder.AppendLine(" order by FNo");

第一个问题就是,这段SQL代码是什么样意思?
变量解释:
FExchangeRate 直接汇率
T_BD_RATE 汇率的数据表
FForbidderID 禁用者ID
FRateTypeID 汇率类型 
FCYForID 目标汇率币别 (外汇汇率)
FCYToID 本位币币别
FBegDate 开始时间
FEndDate 结束时间 
FREVERSEEXRATE 间接汇率 
FFORBIDSTATUS 禁用状态 
FDOCUMENTSTATUS 审核状态

代码解释:
在T_BD_RATE 汇率的数据表 中选出 FExchangeRate 直接汇率
FForbidderID 禁用者ID 为 0 FRateTypeID汇率类型为 @RateTypeID
FCYForID目标汇率币别 为 @CyForID  并且 本位币币别为 @CyToID
FBegDate 开始时间 小于等于 @BegDate 并且 FEndDate 结束时间 大于等于@EndDate
FFORBIDSTATUS 禁用状态  为非禁用 FDOCUMENTSTATUS 审核状态 为 已审核

下一段sql代码基本一致,除了第一句选出的是 FREVERSEEXRATE 间接汇率 
这里我并不明白为什么要这么做,再UNION, 我只用第一段SQL代码便可以实现取汇率了
写为python

stringBuilder = StringBuilder()

创建一个StringBuilder的类,这里要注意引入clr.AddReference("System")
from System.Text import *
这个类是来源于System.Text

stringBuilder.AppendLine(" select FPRICE3 FROM T_BD_RATE ")
stringBuilder.AppendLine("where FForbidderID=0 and FBEGDATE = @FBegDate ")
stringBuilder.AppendLine("and FRATETYPEID = @FRateTypeId ")
stringBuilder.AppendLine("and FCYTOID = @FCyToId")
stringBuilder.AppendLine("and FCYFORID = @FCyForId and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ")
    
这里直接按照他原文照写 , FPRICE3是我需求中的卖出价汇率,各位替换成为自己的字段名
C#
            List<SqlParam> list = new List<SqlParam>();
            list.Add(new SqlParam("@RateTypeID", DbType.Int64, iRateTypeID));
            list.Add(new SqlParam("@CyForID", DbType.Int64, iCurrencyFromID));
            list.Add(new SqlParam("@CyToID", DbType.Int64, iCurrencyToID));
            list.Add(new SqlParam("@BegDate", DbType.DateTime, RateDate.Date));
            list.Add(new SqlParam("@EndDate", DbType.DateTime, RateDate.Date));
这段代码的解释:
创建一个SqlParam类型的List
并且在这个List中添加用于SQL查询的变量 

Python
List的使用需要
clr.AddReference("System.Collections")
from System.Collections.Generic import *

SqlParam:
clr.AddReference('Kingdee.BOS')
from Kingdee.BOS import *

DbType:
clr.AddReference("System.Data")
from System.Data import *

    list = List[SqlParam]() #重点关注这里,在IronPython中使用中括号的方式声明泛型
    list.Add(SqlParam("@FRateTypeId", DbType.Int64, 2))
    list.Add(SqlParam("@FBegDate", DbType.DateTime, Date))
    list.Add(SqlParam("@FCyToId", DbType.Int64, FRmbId))
    list.Add(SqlParam("@FCyForId", DbType.Int64, FCurrencyId))
C#
            decimal result = 0m;
            using IDataReader dataReader = DBUtils.ExecuteReader(ctx, stringBuilder.ToString(), list);
            if (dataReader.Read())
            {
                result = DBReaderUtils.GetValue<decimal>(dataReader, 0);
            }

            dataReader.Close();
            return result;
代码解释:
result是返回结果 
使用ExecuteReader执行SQL语句,list是刚刚我么设定好的参数
如果,dataReader.Read()不为空
result结果就是GetValue(dataReader,索引为0)
为何索引为0,因为我们的SQL语句只会取出一个结果,所以固定位0就行


DBUtils引用:
clr.AddReference('Kingdee.BOS.App')
from Kingdee.BOS.App.Data import *

DBReaderUtils引用:
clr.AddReference('Kingdee.BOS')
from Kingdee.BOS.Util import *

Decimal:
clr.AddReference("System")
from System import *

python:

    dataReader = IDataReader #重点,可以这样为这个接口赋值
    dataReader = DBUtils.ExecuteReader(this.Context, stringBuilder.ToString(), list);
    result = 0.0 #将默认为decimal的值,而不是声明为0时的int值
    if dataReader.Read():
        result = DBReaderUtils.GetValue[Decimal](dataReader, 0) #重点!使用这种方法来声明泛型的结果 
    dataReader.Close()
    
    return result

整体就结束了,其中的python转换重点就是 

StringBuilder stringBuilder = new StringBuilder();

stringBuilder = StringBuilder()


string = String()


List<SqlParam> list = new List<SqlParam>();

list = List[SqlParam]()


using IDataReader dataReader = DBUtils.ExecuteReader(ctx, stringBuilder.ToString(), list);

dataReader = IDataReader


result = DBReaderUtils.GetValue<decimal>(dataReader, 0);

result = DBReaderUtils.GetValue[Decimal](dataReader, 0)


python整体代码:

import clr
clr.AddReference("System")
clr.AddReference("System.Collections")
clr.AddReference("System.Data")
clr.AddReference('Kingdee.BOS.App')
clr.AddReference('Kingdee.BOS')

from Kingdee.BOS.App.Data import *
from System.Text import *
from System import *
from System.Collections.Generic import *
from Kingdee.BOS import *
from System.Data import *
from Kingdee.BOS.Util import *

#获取汇率
def Exchange():
    stringBuilder = StringBuilder()
    string = String()
   
    FCurrency = this.View.Model.GetValue("FSellCurrencyId") #授信币别
    if (FCurrency == None):
        return
    FCurrencyId = FCurrency["Id"]
    FRmb = this.View.Model.GetValue("FLocCurrencyId") #本位币
    if (FRmb == None):
        return
    FRmbId = FRmb["Id"]
    Date = this.View.Model.GetValue("FSignDate") #日期
    if (Date==None):
        return
   
    if FCurrencyId == FRmbId:#本位币等于授信币别的时候 汇率为1
        this.Model.SetValue("FDealDateExcRate", 1.0)
        return
   
    stringBuilder.AppendLine(" select FPRICE3 FROM T_BD_RATE ")
    stringBuilder.AppendLine("where FForbidderID=0 and FBEGDATE = @FBegDate ")
    stringBuilder.AppendLine("and FRATETYPEID = @FRateTypeId ")
    stringBuilder.AppendLine("and FCYTOID = @FCyToId")
    stringBuilder.AppendLine("and FCYFORID = @FCyForId and FFORBIDSTATUS = 'A' and FDOCUMENTSTATUS = 'C' ")
       
    list = List[SqlParam]()
    list.Add(SqlParam("@FRateTypeId", DbType.Int64, 2))
    list.Add(SqlParam("@FBegDate", DbType.DateTime, Date))
    list.Add(SqlParam("@FCyToId", DbType.Int64, FRmbId))
    list.Add(SqlParam("@FCyForId", DbType.Int64, FCurrencyId))

    dataReader = IDataReader
    dataReader = DBUtils.ExecuteReader(this.Context, stringBuilder.ToString(), list);
    result = 0.0
    if dataReader.Read():
        result = DBReaderUtils.GetValue[Decimal](dataReader, 0)
    dataReader.Close()

    this.View.Model.SetValue("FDealDateExcRate", result) #汇率
    this.View.InvokeFieldUpdateService("FDealDateExcRate",0)
    this.View.UpdateView("FDealDateExcRate")
   
def DataChanged(e):
    if e.Field.Key.ToString().lower() == "FSignDate".lower():
        Exchange()
   
def AfterBindData(e):
    if this.Model.GetValue("FDealDateExcRate") == 0:
        Exchange()


如果没有选择日期就更新汇率值,把日期属性中的 立即触发值更新事件 勾选上

图标赞 84
84人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!