在做SAPUI5开发时,我们会需要做的特定的ACTIONS动作操作,比如,把选定的行进行采购收货,交货,或者做发票校验等操作,这些操作,我们都需要在SAP Gateway做好后端开发,也就是做ODATA的对应功能,给前端SAPUI5使用。
在做ODATA时,我有三个想法,
1.使用Entity的CREATE方法,在POST的方法中实现,但测试后现发在前端OMODEL.create时,只能提交单行,而在一些操作时,我们所需要的是一次提交多行,所以此方法没成,也考虑在PUT,MERGE中实现,但还没测试,不过,可能性很小,应该也不行。
2.使用Function Imports,此法在SEGW中创建一个Function 的功能来给前端调用,此文章主要介绍此法。
3.BOPF中定义,就是在消费的CDS中引用有BOPF的CDS视图,并在BOPF中定义好ACTIONS,此时我们在使用时就可以直接使用此ACTIONS了,前端使用方法使用与Function Imports的一样,在这里可查看实例。
以下以定义一个采购收货的功能为例子说明,
1.ODATA实现
1.1.创建动作动作函数的返回参数结构,
可以先用SE11定义好结构,并在SEGW中引入。在此引入岐途的Entity为ZGR_RETURN
1.2.创建动作函数Entity
在SEGW中创建一个Function Imports,名字为:ZFM_GR_MIGO,并在返回类型 Return type 中使用用上一步创建好的Entity:ZGR_RETURN.把HTTP Method Type 设置成POST.
注:以多次测试发现这里的类型不论是设置成POST,还是GET,后面一步使用的参数,其实都是在URL地址中传输,也就是说这里的设置不会影响后面一步的参数的传输方式。
在此Function Imports下创建一个函数的传入参数data1,在前而时我们把所要收货的数据按JSON格式,转换成字符串STRING传入到这个参数中,我们在SAP后面直接用DATA1的值转换成结构数据处理就行
注:在可以设置多个,但这里设置的参数只能在URL中传输也就是说相当于是GET参数,而不会是真正的POST参数,
2.查验证功能
生成SEGW项目后,我们查看项目的,$metadata,就会发现多了一个FunctionImport 功能,在前面我设置了一个action-for entity 所以在这里显示器:ZFIORI1_SRV.ZGR_EKPO,当前例子没使用这个,所以在这里就不做说明,不影响我们的功能。
1 2 3 4 5 6 7 8 9 10 11 |
<FunctionImport Name="ZFM_GR_MIGO" EntitySet="ZGR_RETURNSet" sap:action-for="ZFIORI1_SRV.ZGR_EKPO" m:HttpMethod="POST" ReturnType="ZFIORI1_SRV.ZGR_RETURN"> <Parameter Name="data1" MaxLength="1000" Type="Edm.String" Mode="In"/> </FunctionImport> |
3.写入动作功能代码
实现SEGW的项目类***_DPC_EXT的,/IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION 方法,此方法中放入所有此项目的动作功能,在代码中IV_ACTION_NAME中存放了传入Function Imports名字。所以我们需要在这里通过判断此值的不同来进行不同的处理,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
METHOD /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION. DATA: LS_PARAMETER TYPE /IWBEP/S_MGW_NAME_VALUE_PAIR. DATA: L_JSON TYPE STRING, LS_RECORD TYPE ZMM_C_POEKPO2V, LT_RECORD TYPE TABLE OF ZMM_C_POEKPO2V. BREAK YANGSEN. IF IV_ACTION_NAME = 'ZFM_GR_MIGO'. " Check what action is being requested READ TABLE IT_PARAMETER INTO LS_PARAMETER WITH KEY NAME = 'data1'. IF SY-SUBRC = 0 . L_JSON = LS_PARAMETER-VALUE. /UI2/CL_JSON=>DESERIALIZE( EXPORTING JSON = L_JSON CHANGING DATA = LT_RECORD ). "收货过账。 CALL FUNCTION 'ZMM_PO_MIGO_GR' EXPORTING LT_DATA = LT_RECORD . ENDIF. ENDIF. ENDMETHOD. |
我们的目的是得到传入的数据,而传入的数据,在前面只定义一个DATA1的变量,所以在这里先得到传入的变量的值班,再把此值作为一个JSON的字符串处理,转换出结构来,在这里定义的传入的数据结构是一个CDS生成的结构,我们也可以按需求定义一个自己的结构,在传入时使用就行。
程序中调用 /UI2/CL_JSON=>DESERIALIZE把JSON的字符串转换成一个数据结构内表LT_RECORD.
调用自己的数据处理函数ZMM_PO_MIGO_GR,进行收货,
后面应该还要把处理的结果返回到类返回参数ER_DATA中,这就简单的,细节可以自己想,
另外就是还要有错误处理功能,后面再继写。
4.测试函数功能
测试此项目时,我们把传入的数据转换为字符串,传入的DATA1中,并使用POST方法调用地址:/sap/opu/odata/SAP/ZFIORI1_SRV/ZFM_GR_MIGO?data1='[{“ebeln”:”4500000103″,”ebelp”:”00010″,”zshsl”:10},{“ebeln”:”4500000103″,”ebelp”:”00020″,”zshsl”:10}]’,就能把数据传入到我们写的代码中了,在这里发现,我们要传递的数据要写成URL的地址中,并给变量DATA1,那就会出现如这个数据中存在一些特殊字符时就会出错,比如中文,但这个问题在SAPUI5前端调用时是不存在,因为前端调用时会对字符串自动URL编码,会把中文及一些特殊字符进行编码,如你要这里测试中使用一些中文或者其它的特殊字符中,可以先对数据进行URL编码。
5.在前端SAPUI5中调用
在前端调用时,我们使用MODEL的callFunction方法调用此方法,并把数据传递过来就行,以下为收货时的按钮代码,完整体的SAPUI5采购还在优化中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
onGRMigo:function(){ var that = this; var _omodel = this.getModel(); var odata = []; var _olist = this.byId("list"); var items = _olist.getSelectedItems(); if(items.length < 1){ MessageToast.show( "请选择要收货的行"); return; } // 在这里组装出需要确认收货的数据。 for (var i = 0; i < items.length; i++) { var item = items[i]; var context = item.getBindingContext(); var obj = context.getProperty(null, context); odata[i]= obj; } var ParaData = JSON.stringify(odata); _omodel.callFunction("/ZFM_GR_MIGO",{ "method": "POST", urlParameters: {"data1": ParaData }, // function import parameters success: function(oData, response) { MessageToast.show("收货成功"); }, // callback function for success error: function(oError){ MessageToast.show( oError); } }); // callback function for error }, |
为什么我的SEGW里新建并没有FUNCTION INMPORT呢?只有一个创建实体类型。
应该都有的吧
换成英文试试
这篇文章说的,CREATE方法只能提交单行,其实用batch处理就能解决提交多行的问题了,在后台会走多次create方法。删除更新查询方法同理,也可以用batch处理提交多个请求