zoukankan      html  css  js  c++  java
  • 使用SAP CDS view快速创建一个Fiori应用,管理Service Order

    In this blog, I will show you how to create a CRM Service Order Fiori application within just a couple of minutes. You don’t need to write even one line of JavaScript code to get this responsive application.

    Main function of this Fiori application

    (1) There is a list which shows overview of Service orders in CRM system. You can search by Service Order and order description in search field.

    (2) By clicking the setting icon, you can make more table columns visible in the table:

    Example: Additional two columns are exposed.

    Example: Sort by Posting date in ascending order

    Example: Group by Order Status:

    (3) Select any table row, you can navigate to Service Order detail page:

    You can click corresponding tab to reach each detail page area:

    Keep in mind, you DO NOT NEED to write any JavaScript code to make the above functionalities work. Please note that service order change and save are not supported in this application yet.

    【Update on 2016-04-10】: Update function is available now. Please refer to this blog for detail: Enable CRM Service Order application with edit functionality.

    Prerequisite of this solution

    (1) SAP Web IDE 1.17 (includes OData Annotation Modeler as an available plug-in)
    (2) SAP Netweaver 7.5 SP01
    (3) You need to have some basic knowledge on CDS view. Here is the documentation of CDS view in SAP help
    (4) You need to have some basic knowledge on UI5 Smart template. This is documentation in SAP help: Developing Apps with Smart Templates

    Implementation steps

    The overall development process would be:

    (1) Most of the effort could be the CDS view implementation. Those views are responsible to return necessary data to UI frontend.

    (2) The corresponding OData service is automatically generated when you activated your CDS view.

    (3) Then you can use WebIDE Smart template generation wizard to generate the Fiori application on top of the automatically generated OData service.

    The following entities must be created in ABAP development studio.

    You can just paste the source code of each entity into ABAP development studio and activate them one by one.

    Z_C_Status_Text

    For example, create a new CDS view in ABAP development studio and paste the following source code,

    @AbapCatalog.sqlViewName: 'zstatustext'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'system status code and description'
    define view Z_C_Status_Text as select from tj02 inner join tj02t as _tj02t on
    tj02.istat = _tj02t.istat and _tj02t.spras = 'E'                    
    {
      key tj02.istat,
      _tj02t.txt04,
      _tj02t.txt30
    }
    

    then click activate button:

    Z_I_Prod_Status

    @AbapCatalog.sqlViewName: 'zprdstatus'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'product guid and status code'
    define view Z_I_Prod_Status as select from crmd_product_i
    inner join crm_jest as _status on crmd_product_i.guid = _status.objnr
    inner join Z_C_Status_Text as _text on _status.stat = _text.istat
    {
      key crmd_product_i.guid,
      _status.stat,
      _text.txt04,
      _text.txt30
    }
    where _status.inact = '' and _status.stat like 'I%' and _status.stat <> 'I1030';
    

    Z_I_Item_Detail

    @AbapCatalog.sqlViewName: 'zitemdetail'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'item detail'
    define view Z_I_Item_Detail as select from crmd_orderadm_i
    inner join crmd_schedlin as _schedule
      on crmd_orderadm_i.guid = _schedule.item_guid
    inner join crmd_product_i as _prod on crmd_orderadm_i.guid = _prod.guid
    inner join Z_I_Prod_Status as _prd_status
      on crmd_orderadm_i.guid = _prd_status.guid
    {
      key crmd_orderadm_i.guid,
      key crmd_orderadm_i.header,
      @UI.lineItem : [{position:10, label : 'Item Number'}]
      crmd_orderadm_i.number_int,
      @UI.lineItem : [{position:20, label : 'Product Name'}]
      crmd_orderadm_i.description,
      @UI.lineItem : [{position:30, label : 'Quantity'}]
      _schedule.quantity,
      @UI.lineItem : [{position:40, label : 'Unit'}]
      _prod.process_qty_unit as unit,
      _prd_status.stat,
      _prd_status.txt04,
      @UI.lineItem : [{position:50}]
      _prd_status.txt30
    }
    

    Z_C_Order_Item

    @AbapCatalog.sqlViewName: 'zorderitem'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'order item detail'
    define view Z_C_Order_Item as select from crmd_orderadm_h
    inner join crmc_proc_type as _type on crmd_orderadm_h.process_type =
        _type.process_type and _type.object_type = 'BUS2000116'
    association [0..*] to Z_I_Item_Detail as _Item
    on $projection.guid = _Item.header
    {
      key crmd_orderadm_h.guid,
      key crmd_orderadm_h.object_id,
      crmd_orderadm_h.description,
      crmd_orderadm_h.posting_date,
      @ObjectModel.association.type: #TO_COMPOSITION_CHILD
      _Item
    }
    

    Zorder_Sys_Status

    @AbapCatalog.sqlViewName: 'zsystatus'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'system status'
    define view Zorder_Sys_Status as select from crmd_orderadm_h
    inner join crm_jest as _crm_jest on crmd_orderadm_h.guid = _crm_jest.objnr
    inner join Z_C_Status_Text as _status_text on _crm_jest.stat = _status_text.istat
                                                
    {
      key crmd_orderadm_h.guid,
      key _crm_jest.stat,
      _status_text.txt04,
      _status_text.txt30
    }
    /*where _crm_jest.inact = '' and _crm_jest.stat like 'I%' and _crm_jest.stat <> 'I1030' // has error
    and _crm_jest.stat <> 'I1026'; // do not transfer*/
    where _crm_jest.inact = '' and ( _crm_jest.stat = 'I1003' or
    _crm_jest.stat = 'I1003' or _crm_jest.stat = 'I1005' )
    /*I1002 open
    I1003 in process
    I1005 complete*/
    

    Z_c_partner

    @AbapCatalog.sqlViewName: 'zcpartner'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'partner detail'
    define view Z_c_partner as select from crmd_orderadm_h
    inner join crmd_link as _link on crmd_orderadm_h.guid = _link.guid_hi and _link.objtype_hi = '05'
      and _link.objtype_set = '07'
    inner join ztf_bp_detail( clnt: '001') as _bp on _link.guid_set = _bp.partset_guid
    {
      key crmd_orderadm_h.guid,
      --_link.objtype_hi as header_type,
      --_link.objtype_set as item_type,
      _bp.bp_guid,
      _bp.partner_no,
      _bp.name,
      case _bp.title
        when '0001' then 'Ms.'
        when '0002' then 'Mr.'
        when '0003' then 'Company'
        when '0004' then 'Mr and Mrs'
        else 'Unknown'
      end as title
    }
    

    ztf_BP_DETAIL

    @ClientDependent: true
    @AccessControl.authorizationCheck: #NOT_REQUIRED
    define table function ztf_BP_DETAIL
      with parameters @Environment.systemField: #CLIENT
                      clnt:abap.clnt
      returns { client:s_mandt;
                partner_guid:BU_PARTNER_GUID;
                partset_guid:CRMT_OBJECT_GUID;
                partner_no: CRMT_PARTNER_NO;
                bp_guid: BU_PARTNER_GUID;
                title:AD_TITLE;
                name: BU_NAME1TX;
              }
      implemented by method
        zcl_amdp_bp_detail=>crmd_partner_but000;
    

    zcl_amdp_bp_detail

    CLASS zcl_amdp_bp_detail DEFINITION
      PUBLIC
      FINAL
      CREATE PUBLIC .
      PUBLIC SECTION.
      INTERFACES if_amdp_marker_hdb.
      CLASS-METHODS crmd_partner_but000 FOR TABLE FUNCTION ztf_bp_Detail.
      PROTECTED SECTION.
      PRIVATE SECTION.
    ENDCLASS.
    CLASS zcl_amdp_bp_detail IMPLEMENTATION.
    METHOD crmd_partner_but000
            BY DATABASE FUNCTION FOR HDB
            LANGUAGE SQLSCRIPT
            OPTIONS READ-ONLY
            USING crmd_partner but000.
        RETURN SELECT sc.client as client,
                      sc.partner_guid as partner_guid,
                      sc.guid as partset_guid,
                      sc.partner_no as partner_no,
                      sp.partner_guid as bp_guid,
                      sp.title as title,
                      sp.name1_text as name
                      FROM crmd_partner AS sc
                        INNER JOIN but000 AS sp ON sc.client = sp.client AND
                                                  sc.partner_no = sp.partner_guid
                        WHERE sc.client = :clnt AND
                              sc.partner_fct = '00000001'
                        ORDER BY sc.client;
      ENDMETHOD.
    ENDCLASS.
    

    For CDS table function and AMDP implementation, please read this blog My CDS view self study tutorial – Part 6 consume table function in CDS view for more detail.

    Z_i_Order_View

    @AbapCatalog.sqlViewName: 'ziorder'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'order consumption view'
    define view Z_i_Order_View as select from Z_C_Order_Item
    inner join Zorder_Sys_Status as _sys_status
    on Z_C_Order_Item.guid = _sys_status.guid
    inner join Z_c_partner as _partner
    on Z_C_Order_Item.guid = _partner.guid
    {
      key Z_C_Order_Item.guid as order_guid,
      Z_C_Order_Item.object_id,
      Z_C_Order_Item.description,
      Z_C_Order_Item.posting_date,
      _partner.name,
      _partner.partner_no,
      _partner.title,
      _sys_status.stat,
      _sys_status.txt04,
      _sys_status.txt30,
      @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
      Z_C_Order_Item._Item
    }
    

    Z_C_Service_Order_View

    @AbapCatalog.sqlViewName: 'zcorderview'
    @AbapCatalog.compiler.compareFilter: true
    @AccessControl.authorizationCheck: #CHECK
    @EndUserText.label: 'service order consumption view'
    @Search.searchable: true
    @OData.publish: true
    @ObjectModel: {
      type: #CONSUMPTION,
      compositionRoot,
      createEnabled,
      deleteEnabled,
      updateEnabled
    }
    @UI.headerInfo:{
      typeName:      'Service Order',
      typeNamePlural: 'Service Orders',
      title: { value: 'object_id' },
      description: { value: 'description' }
    }
    define view Z_C_Service_Order_View as select from Z_i_Order_View {
      key Z_i_Order_View.order_guid as order_guid,
      @UI.lineItem : [{position:10, label : 'Service Order ID'}]
      // @UI.identification: [ { position: 10 } ]
      @UI.selectionField: [ { position: 20, label : 'Service Order ID' } ]
      Z_i_Order_View.object_id,
      @UI.lineItem : [{position:20, label : 'Description'}]
      //@UI.identification: [ { position: 20 } ]
      @Search:{ defaultSearchElement: true, ranking: #HIGH, fuzzinessThreshold: 0.8 }
      //@UI.selectionField: { position: 4, element: '_ProductCategory.MainProductCategory' }
      @UI.selectionField: [ { position: 10, label : 'Description' } ]
      Z_i_Order_View.description,
      Z_i_Order_View.partner_no,
      Z_i_Order_View.title,
      @UI.identification: [ { position: 20 } ]
      Z_i_Order_View.posting_date,
      @UI.lineItem : [{position:30, label : 'Account'}]
      @UI.identification: [ { position: 30, label : 'Account' } ]
      Z_i_Order_View.name,
      Z_i_Order_View.stat,
      Z_i_Order_View.txt04,
      @UI.lineItem : [{position:40}]
      @UI.identification: [ { position: 40 } ]
      Z_i_Order_View.txt30,
      @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
      Z_i_Order_View._Item
    }
    

    Once you have activated all the CDS view entities, follow the steps described in this blog Step by Step to create CDS view through SmartTemplate + WebIDE, and you will get the working Service order application immediately.

    Further reading

    If you have a look at the automatically generated project in WebIDE, you will find that now there is no application specific view or controllers. Only Component.js exists with a few dummy code below. The UI5 runtime takes over everything for you to make the application work.

    It means your trouble shooting will become more struggled in case you meet with isuse, since now the whole scenarios works as a black box for you. As a result it is of great importance for developers to understand what occurs under the hood.

    CDS view self study

    The following posts are written by me during my self-study on CDS view:

    要获取更多Jerry的原创文章,请关注公众号"汪子熙":

  • 相关阅读:
    git subtree用法
    Excel导入、导出库:ExcelKit
    [C#.NET 拾遗补漏]08:强大的LINQ
    使用.net standard实现不同内网端口的互通(类似花生壳)
    LINQ:最终统治了所有的语言!
    浅谈代码段加密原理(防止静态分析)
    HashTable、HashSet和Dictionary的区别(转)
    Mysql分表和分区的区别、分库分表介绍与区别
    划词高亮功能的实现附带开源代码
    十个推荐使用的 Laravel 的辅助函数
  • 原文地址:https://www.cnblogs.com/sap-jerry/p/13612842.html
Copyright © 2011-2022 走看看