S4 Hana Cloud-自定义业务对象创建发布与OData更新数据

1.自定义业务对象创建与发布OData服务

image.png

image.png

image.png

image.png

image.png

保存前节点替换代码

* Before Save Validation for Node ID SALESTOPURCHASE
*
* Importing Parameter : association (Navigation to Parent/Child/Associated Node Instances)
*                       SALESTOPURCHASE (Current Node Data)
* Exporting Parameter : valid (abap_true or abap_false)
*                       message (Message Text String)
*                       attribute (Attribute Name)

**数据检查*****数据检查******数据检查*******数据检查*****

IF salestopurchase-belnr IS NOT INITIAL.
  DATA(belnr) = salestopurchase-belnr.
  DATA(len) = 10 - strlen( belnr ).
  DO len TIMES.
    belnr = |0| & |{ belnr }|.
  ENDDO.
  CLEAR len.
ENDIF.
SELECT SINGLE COUNT(*) FROM i_salesorder WHERE salesorder EQ @belnr .
IF sy-subrc NE 0.
  message = | 销售订单号不存在 |.
  RETURN.
ENDIF.

SELECT SINGLE COUNT(*) FROM i_companycode WHERE companycode EQ @salestopurchase-bukrs .
IF sy-subrc NE 0.
  message = | 公司代码不存在 |.
  RETURN.
ENDIF.

SELECT SINGLE COUNT(*) FROM i_plant WHERE plant EQ @salestopurchase-werks .
IF sy-subrc NE 0.
  message = | 工厂不存在 |.
  RETURN.
ENDIF.

DATA(lifnr) = salestopurchase-lifnr.
len = 10 - strlen( lifnr ).
DO len TIMES.
  lifnr = |0| & |{ lifnr }|.
ENDDO.
CLEAR len.
SELECT SINGLE COUNT(*)
FROM i_supplierpurchasingorg
WHERE supplier EQ @lifnr
AND purchasingorganization EQ @salestopurchase-vkorg.
*AND purchasinggroup EQ @salestopurchase-ekorg.
IF sy-subrc NE 0.
  message = | 供应商无此采购组织视图 |.
  RETURN.
ENDIF.

SELECT SINGLE COUNT(*) FROM i_product WHERE product EQ @salestopurchase-matnr.
IF sy-subrc NE 0.
  message = | 物料不存在 |.
  RETURN.
ENDIF.

IF salestopurchase-matnr+0(1) NE 'S'.
  message = | 只允许使用服务型物料 |.
  RETURN.
ENDIF.

IF salestopurchase-wrbtr_v IS INITIAL.
  message = | 金额不允许为0 |.
  RETURN.
ENDIF.

IF salestopurchase-wrbtr_c NE 'CNY'.
  message = | 单位必须为CNY |.
  RETURN.
ENDIF.

SELECT SINGLE COUNT(*) FROM i_taxcode WHERE taxcode EQ @salestopurchase-mwskz.
IF sy-subrc NE 0.
  message = | 税码不存在 |.
  RETURN.
ENDIF.
**数据检查*****数据检查******数据检查*******数据检查*****

valid = abap_true.

创建采购订单标签替换代码

* Action ACTION001 for Node ID SALESTOPURCHASE
*
* Importing Parameter : association (Navigation to Parent/Child/Associated Node Instances)
*                       write (API for creating and updating Custom Business Object Node Instances)
* Changing Parameter  : SALESTOPURCHASE (Current Node Data)
* Exporting Parameter : message (Message with Severity S(uccess), W(arning), E(rror))

*message = VALUE #(
*  severity = co_severity-success
*  text     = 'Action ACTION001 executed'
*).

SELECT SINGLE COUNT(*)
FROM i_purchaseorderapi01
WHERE purchaseorder EQ @salestopurchase-ebeln
AND   purchasingdocumentdeletioncode NE @abap_true.
IF sy-subrc EQ 0.
  message = VALUE #( severity = co_severity-error text = '不允许重复生成采购订单' ).RETURN.
ENDIF.

DATA: lv_available    TYPE abap_bool.
cl_ble_http_client=>is_service_available(
   EXPORTING
   communication_scenario = 'YY1_INT_HTTP'
   outbound_service       = 'YY1_INT_HTTP_REST'
   RECEIVING
   available              = lv_available ).

IF lv_available NE abap_true.
  message = VALUE #( severity = co_severity-error text = '通信安排错误' ).RETURN.
ENDIF.

DATA(lo_client) = cl_ble_http_client=>create(
                  communication_scenario = 'YY1_INT_HTTP'
                  outbound_service       = 'YY1_INT_HTTP_REST' ).

*********获取token***********************************
DATA lv_u1 TYPE string VALUE '/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder'.
DATA:lv_u2 TYPE string VALUE '?$top=1'.

DATA: lt_headerparam TYPE tihttpnvp,
      ls_header      TYPE LINE OF tihttpnvp.

ls_header-name = 'Accept'.
ls_header-value = 'application/json'.
APPEND ls_header TO lt_headerparam.

ls_header-name = 'x-csrf-token'.
ls_header-value = 'fetch'.
APPEND ls_header TO lt_headerparam.

lv_u2 = lv_u1 && lv_u2.

DATA(request) = cl_ble_http_request=>create( )->set_method( 'GET' )->set_resource_extension( lv_u2 )->set_header_parameters( parameters =  lt_headerparam ).
CLEAR:lt_headerparam,ls_header.

TRY .
    DATA(response) = lo_client->send( request ).
    DATA(lv_token) = response->get_header_parameter( name = 'x-csrf-token' ).
  CATCH cx_ble_http_exception INTO DATA(lx).
    message = VALUE #( severity = co_severity-error text = lx->get_text( ) ).
    RETURN.
ENDTRY.


*****构造JSON POST创建订单******************************************
DATA:lv_post_body TYPE string,
     lv_post_head TYPE string,
     lv_post_item TYPE string.
DATA:
  lv_field1  TYPE string VALUE '"CompanyCode": ',
  lv_field2  TYPE string VALUE '"PurchaseOrderType": "NB"',
  lv_field3  TYPE string VALUE '"Supplier": ',
  lv_field4  TYPE string VALUE '"PurchasingOrganization": ',
  lv_field5  TYPE string VALUE '"PurchasingGroup": ',
  lv_field6  TYPE string VALUE '"DocumentCurrency":"CNY" ',
  lv_field7  TYPE string VALUE '"PurchaseOrderDate": ',

  lv_field8  TYPE string VALUE '"PurchaseOrderItem": ',
  lv_field9  TYPE string VALUE '"Plant": ',
  lv_field10 TYPE string VALUE '"NetPriceAmount": ',
  lv_field11 TYPE string VALUE '"OrderQuantity": "1"',
  lv_field12 TYPE string VALUE '"PurchaseOrderItemCategory": "0"',
  lv_field13 TYPE string VALUE '"AccountAssignmentCategory": "Z"',
  lv_field14 TYPE string VALUE '"Material": ',
  lv_field15 TYPE string VALUE '"AccountAssignmentNumber":"1" ',
  lv_field16 TYPE string VALUE '"CostCenter": ',
  lv_field17 TYPE string VALUE '"SalesOrder": ',
  lv_field18 TYPE string VALUE '"SalesOrderItem": ',
  lv_field19 TYPE string VALUE '"PurchasingDocumentItem": ',
  lv_field20 TYPE string VALUE '"ScheduleLine":"1" ',
  lv_field21 TYPE string VALUE '"ScheduleLineDeliveryDate": ',
  lv_field22 TYPE string VALUE '"TaxCode":'.

DATA:lv_node1 TYPE string VALUE '"to_PurchaseOrderItem": ',
     lv_node2 TYPE string VALUE '"to_AccountAssignment": ',
     lv_node3 TYPE string VALUE '"to_ScheduleLine": ',
     lv_node4 TYPE string VALUE '{ "results":[{'.

**********获取销售订单行项目数据******************************

DATA(len) = 10 - strlen( salestopurchase-belnr ).
DO len TIMES.
  salestopurchase-belnr = |0| & |{ salestopurchase-belnr }|.
ENDDO.

SELECT *
  INTO TABLE @DATA(lt_order)
  FROM i_salesdocumentitem
  WHERE salesdocument EQ @salestopurchase-belnr.

SHIFT salestopurchase-belnr LEFT DELETING LEADING '0'.

DATA:ls_order TYPE i_salesdocumentitem.

DATA lv_netamount TYPE i_salesdocumentitem-netamount. "total amount
DATA lv_wrbtr_sum TYPE i_salesdocumentitem-netamount.
DATA lv_wrbtr     TYPE i_salesdocumentitem-netamount.

LOOP AT lt_order INTO ls_order.
  lv_netamount = lv_netamount + ls_order-netamount.
ENDLOOP.

**********时间戳处理****************************************
DATA:my_timestamp TYPE timestamp,
     lv_date      TYPE c LENGTH 8,
     lv_time      TYPE c LENGTH 6,
     lv_timestamp TYPE string,
     timestamp1   TYPE timestamp VALUE '19700101000000',
     timestamp2   TYPE timestamp.

GET TIME STAMP FIELD my_timestamp.
lv_timestamp = | { my_timestamp TIMESTAMP = ISO TIMEZONE = 'UTC+8' } |.
CONDENSE lv_timestamp NO-GAPS.
lv_date = lv_timestamp+0(4) && lv_timestamp+5(2) && lv_timestamp+8(2).
lv_time = lv_timestamp+11(2) && lv_timestamp+14(2) && lv_timestamp+17(2).
timestamp2 = lv_date && lv_time.
DATA(seconds) = cl_abap_timestamp_util=>get_instance( )->tstmp_seconds_between(
               EXPORTING iv_timestamp0 = timestamp1 iv_timestamp1 = timestamp2 ) * 1000 - 28800000.
DATA(sjc) = |/Date({ seconds })/|.


lv_post_body = |{ lv_field1 }"{ salestopurchase-bukrs }",| &
               |{ lv_field2 },| &
               |{ lv_field3 }"{ salestopurchase-lifnr }",| &
               |{ lv_field4 }"{ salestopurchase-vkorg }",| &
               |{ lv_field5 }"{ salestopurchase-ekorg }",| &
               |{ lv_field6 },| &
               |{ lv_field7 }"{ sjc }",| &
               |{ lv_node1 }{ lv_node4 }| .

DATA(lv_line) = lines( lt_order ).

LOOP AT lt_order INTO ls_order.

  SHIFT ls_order-salesdocumentitem  LEFT DELETING LEADING '0'.

  IF sy-tabix NE '1' .
    lv_post_item = |\{|.
  ENDIF.

  IF sy-tabix EQ lv_line.

    lv_wrbtr = salestopurchase-wrbtr_v - lv_wrbtr_sum.

    lv_post_item = lv_post_item &&
                   |{ lv_field8 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field9 }"{ salestopurchase-werks }",| &
                   |{ lv_field10 }"{ lv_wrbtr }",| &
                   |{ lv_field22 }"{ salestopurchase-mwskz }",| &
                   |{ lv_field11 },| &
                   |{ lv_field12 },| &
                   |{ lv_field13 },| &
                   |{ lv_field14 }"{ salestopurchase-matnr }",| &
                   |{ lv_node2 }{ lv_node4 }| &
                   |{ lv_field15 },| &
                   |{ lv_field8 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field16 }"{ salestopurchase-kostl }",| &
                   |{ lv_field17 }"{ ls_order-salesdocument }",| &
                   |{ lv_field18 }"{ ls_order-salesdocumentitem }"| &
                   |\}]\},| &
                   |{ lv_node3 }{ lv_node4 }| &
                   |{ lv_field19 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field20 },| &
                   |{ lv_field21 }"{ sjc }"| &
                   |\}]\}\}]\}|.
  ELSE.

    lv_wrbtr = ls_order-netamount / lv_netamount * salestopurchase-wrbtr_v.

    lv_wrbtr_sum = lv_wrbtr + lv_wrbtr_sum.

    lv_post_item = lv_post_item &&
                   |{ lv_field8 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field9 }"{ salestopurchase-werks }",| &
                   |{ lv_field10 }"{ lv_wrbtr }",| &
                   |{ lv_field22 }"{ salestopurchase-mwskz }",| &
                   |{ lv_field11 },| &
                   |{ lv_field12 },| &
                   |{ lv_field13 },| &
                   |{ lv_field14 }"{ salestopurchase-matnr }",| &
                   |{ lv_node2 }{ lv_node4 }| &
                   |{ lv_field15 },| &
                   |{ lv_field8 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field16 }"{ salestopurchase-kostl }",| &
                   |{ lv_field17 }"{ ls_order-salesdocument }",| &
                   |{ lv_field18 }"{ ls_order-salesdocumentitem }"| &
                   |\}]\},| &
                   |{ lv_node3 }{ lv_node4 }| &
                   |{ lv_field19 }"{ ls_order-salesdocumentitem }",| &
                   |{ lv_field20 },| &
                   |{ lv_field21 }"{ sjc }"| &
                   |\}]\}\},|.

  ENDIF.

  lv_post_body = lv_post_body && lv_post_item.

  CLEAR:lv_wrbtr,lv_post_item.

ENDLOOP.
lv_post_body = '{' && lv_post_body && '}'.

ls_header-name = 'Content-type'.
ls_header-value = 'application/json'.
APPEND ls_header TO lt_headerparam.

ls_header-name = 'x-csrf-token'.
ls_header-value = lv_token.
APPEND ls_header TO lt_headerparam.

DATA(requestpost) = cl_ble_http_request=>create( )->set_method( 'POST' )->set_resource_extension( lv_u1 )->set_header_parameters(
                    parameters =  lt_headerparam )->set_body( data =  lv_post_body ).

TRY .
    DATA(responsepost) = lo_client->send( requestpost ).
    DATA(str) = responsepost->get_body( ).
    SPLIT str AT 'PurchaseOrder>' INTO lv_u1 lv_u2.
    SPLIT lv_u2 AT '<' INTO salestopurchase-ebeln lv_u1.
  CATCH cx_ble_http_exception INTO DATA(lx2).
    message = VALUE #( severity = co_severity-error text = lx2->get_text( ) ).
    RETURN.
ENDTRY.

2.使用Postman更新数据

image.png

首先在已发布的OData服务网址后拼接 \$metadata 获取元数据,我们发现 FunctionImport 节点后 Name = YY1_SALESTOPURCHASESap_upsert,这就是我们需要调用的方法。
SAP在发布自定义业务对象时会自动生成Sap_upsert,此功能导入将检查语义键值是否已存在,如果存在,则更新相应的数据。如果不存在,则使用相应数据创建新的业务对象实例。
请注意以下内容:
区分大小写:该链接区分大小写,意味着字段名称必须与自定义业务对象元数据中的字段名称相对应。否则,post 请求会返回错误。
列出所有字段:列出根节点中包含的所有字段。否则,post 请求会返回错误。排序不分先后。
如果在自定义业务对象中定义了日期类型字段,则它必须与相应的 OData 字段类型相对应。
&Date=datetime'2019-01-01T01:00:00''

POST请求URL

https://my300XXX-api.saps4hanacloud.cn/sap/opu/odata/sap/YY1_SALESTOPURCHASE_CDS/YY1_SALESTOPURCHASESap_upsert?BELNR='110'&EBELN=''&BUKRS='D010'&WERKS='D010'&VKORG='D010'&EKORG='DK1'&LIFNR='1000000'&MATNR='S010030010001'&KOSTL='D010X002'&WRBTR_V=2000&MWSKZ='J1'&WRBTR_C='CNY'

注意TOKEN的获取,必须获取https://my300XXX-api.saps4hanacloud.cn/*****前缀的TOKEN

成功


image.png

失败


image.png

关于OData服务调用创建采购订单按钮的可行性还在研究中

以上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容