SAP CDS 开发和Fiori App生成学习笔记

SAP CDS开发环境

Install ABAP Development Tools (ADT) and abapGit Plugin | Tutorials for SAP Developers

Create an ABAP Project in ABAP Development Tools (ADT)

CDS 代码资料

ABAP Keyword Documentation

About ABAP Programming Model for SAP Fiori(CDS UI 注解)

SAP Help Portal

增强或扩展CDS视图 | 优通SAP

1.CDS 开发学习

        BOPF是业务对象处理框架(Business Object Processing Framework,以下简称BOPF),SAP有很多标准的BOPF.

        整体的CDS结构一般做三层,类似于BW,分别是抽取层(View),转换层(Basic),输出层(Consumption),分别对Basis层和Consumption层搭建BOPF框架,Consumption层暴露给Fiori使用

1.1 S/4 三层架构(VDM View types

SAP CDS 开发和Fiori App生成学习笔记_第1张图片

1.2层级

SAP CDS 开发和Fiori App生成学习笔记_第2张图片

1.3约定俗成的命名规则

SAP CDS 开发和Fiori App生成学习笔记_第3张图片

1.4数据抽取层代码(+转换层):

        CDS转换层是主要的逻辑处理部分,抽取层基本不对数据处理,为转换层搭建BOPF框架,激活之后就会产生对应的BOPF(T-code:BOBX) ,这里没有做区分,之后对BOPF这块详解

@AbapCatalog.sqlViewName: 'ZDDL_I_EXEMPTION'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '豁免主控室抽取层BASIC'

@ObjectModel: { compositionRoot: true,
                modelCategory: #BUSINESS_OBJECT,
                transactionalProcessingEnabled: true,
                representativeKey: 'exemption_id',
                draftEnabled: true,
                createEnabled: true,
                updateEnabled: true,
                deleteEnabled: true,
                semanticKey: ['exemption_id'],
                writeDraftPersistence: 'ZACT_EXEMPTION_D' }


//@VDM.viewType: #BASIC
define view ZACT_I_EXEMPTION
  as select from Satc_Ci_Exempt_Dv
  association [1..*] to YACT_I_SATC_EX_CHLOG    as _ex_chlog    on  $projection.exemption_id = _ex_chlog.ExemptionId
  association [1..1] to ZACT_I_SATC_AC_CONTACTS as _ac_contacts on  $projection.objtype     = _ac_contacts.object
                                                                and $projection.objname     = _ac_contacts.obj_name
                                                                and $projection.ds_group_id = _ac_contacts.system_group
{

      @ObjectModel.readOnly: true
  key exemption_id,
      check_scope,
      chkclass,
      chkcode,
      Satc_Ci_Exempt_Dv.object_scope as object_scope,
      objname,
      objtype,
      Satc_Ci_Exempt_Dv.subobjname   as subobjname,
      subobjtype,
      checksum,
      valid_until,
        @UI: {
    lineItem: [ { position: 10, importance: #HIGH } ],
    selectionField: [ { position: 10 } ],
    //      identification:[ { position: 20, importance: #HIGH } ],
    fieldGroup: [{ qualifier: 'HeaderInfo', position: 10, importance: #HIGH }]
    }
      state,
      prev_state,
      applicant,
      appl_last,
      reason,
      appl_comment,
      approver,
      appr_last,
      appr_comment,
      notification_request,
      last_changed,
      deleted,
      exemption_crc,
      back_pack,
      xx_hint,
      data_source_id,
      ds_group_id,
      cast( '' as charg_d ) as charg,
      _ac_contacts.package_name,
//      _ac_contacts.changed_on,

      @ObjectModel.association: {
            type: [#TO_COMPOSITION_CHILD]
        }
      _ex_chlog,
      _ac_contacts
}
//where
//      SerialNumberProfile = '' and //Serial Number ILs to display in LR from 1911CE
//  _ex_chlog.deleted != 'X' //非删除状态

说明:

  1. cast( ( _eket.menge – _eket.wemng ) as obmng ) as OBMNG,第一个as obmng,表示数据结果数据元素为obmng,第二个表示生成的视图字段名为obmng
  2. @Semantics.quantity.unitOfMeasure: ‘meins’ 表示下面的字段数量单位为meins
  3. sum(wemng)   as wemng 汇总明细字段
  4. ------------------------------------------------------------------------------------------
  5. transactionalProcessingEnabled: true, 表示生成BOPF
  6. draftEnabled: true,表示BOPF使用草稿功能,
  7. writeDraftPersistence: ‘ZACT_EXEMPTION_D’表示草稿数据表为ZACT_EXEMPTION_D
  8. 此CDS使用了明细CDS:YACT_I_SATC_EX_CHLOG,所以不能独立激活,需要与后面的一步的CDS一起激活
  9. @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]表示后面的对像为字node对像。

1.5数据消费层代码 

        CDS 输出层 VIEW指消费层,同样要搭建BOPF框架,但不会产生BOPF对象,这一层主要是把CDS发布成ODATA服务暴露给Fiori调用

@AbapCatalog.sqlViewName: 'ZDDL_C_EXEMPTION'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '豁免主控室输出层consumption'
@VDM.viewType: #CONSUMPTION

@Metadata.allowExtensions: true

@ObjectModel: { compositionRoot: true,
                transactionalProcessingDelegated: true,
                createEnabled: true,
                updateEnabled: true,
                deleteEnabled: true,
                semanticKey: ['exemption_id'],
                representativeKey: 'exemption_id',
                draftEnabled: true
                }

@OData.publish: true


define view ZACT_C_EXEMPTION
  as select from ZACT_I_EXEMPTION as _exemption
  //association [0..1] to YACT_REASION        as _reason         on  $projection.reason = _reason.ReasonCode
  //association [0..1] to YACT_SATC_EX_CHLOG  as _ex_chlog       on  $projection.exemption_id = _ex_chlog.ExemptionId
  //  association [0..1] to YACT_SATC_CI_CF_P_E as _satc_ci_cf_p_e on  $projection.chkcode = _satc_ci_cf_p_e.message_id
  association [1..*] to YACT_SATC_EX_CHLOG      as _ex_chlog    on  $projection.exemption_id = _ex_chlog.ExemptionId
//  association [0..1] to ZACT_C_SATC_AC_CONTACTS as _ac_contacts on  $projection.objtype     = _ac_contacts.object
//                                                                and $projection.objname     = _ac_contacts.obj_name
//                                                                and $projection.ds_group_id = _ac_contacts.system_group

  //association [0..*] to tadir               as _tadir          on  $projection.objtype = _tadir.object
  //and $projection.objname = _tadir.obj_name
  //YACT_SATC_AC_RESULTH
{

      //免除标示
  key exemption_id,
      //检查范围
      check_scope,
      //类/接口
      chkclass,
      //消息代码
      chkcode,
      //对象范围
      object_scope,
      //对象名称
      objname,
      //对象类型
      objtype,
      //接口组件
      subobjname,
      //对象类型
      subobjtype,
      //身份
      checksum,
      //过期日期
      valid_until,
      @ObjectModel.mandatory: true
      //免除状态
      state,
      //审批状态
      prev_state,
      //申请人
      applicant,
      //更改日期(申请人)
      appl_last,
      //免除原因
      reason,
      //理由
      appl_comment,
      //审批人
      approver,
      //更改日期(审批者)
      appr_last,
      //理由
      appr_comment,
      //通知请求
      notification_request,
      //更改日期
      last_changed,
      //删除标识 布尔变量(X = 真,空格 = 假)
      deleted,
      //INT4
      exemption_crc,
      //Serialisierte Daten
      back_pack,
      //XX_HINT
      xx_hint,
      //对象提供者
      data_source_id,
      //系统组
      ds_group_id,
      _exemption.package_name,

      //@ObjectModel.readOnly
      //_reason.ReasonText                                     as reason_text,
      //      @ObjectModel.readOnly
      //      _satc_ci_cf_p_e.test_title                             as test_title,
      //      @ObjectModel.readOnly
      //      _satc_ci_cf_p_e.msg_title                              as msg_title,
      //      @ObjectModel.readOnly
      //      cast( case when _tadir.devclass is not null then coalesce( _ac_contacts.package_name, _tadir.devclass ) else '' end as abap.char( 100 ) ) as package_name,
      //      @ObjectModel.readOnly
      //      coalesce( _ac_contacts.author, _tadir.author )         as author,
      //_tadir,
      //_ac_contacts,
      //      _satc_ci_cf_p_e,
      /* Associations */
      //      @ObjectModel: {
      //           association: {
      //               type: [#TO_COMPOSITION_CHILD]
      //           }
      //       }
      //_ex_chlog,
      //_reason
      @ObjectModel.association: {
      type: [#TO_COMPOSITION_CHILD]
      }
      _ex_chlog
}

说明

  1. 激活需要与后面明细的视图一起同时才能激活。
  2. @OData.publish: true,用于生成ODATA服务,但此服务生成后没有激活,如要直接使用此服务的话,可使用事务码/N/IWFND/MAINT_SERVICE在其中添加服务,来添加此服务,或者直接在SEGW中已有的项目中添加此服务。
  3. updateEnabled: true,设置可以修改,用于修改收货数量,
  4. deleteEnabled: true,设置可以删除数据,如不做增强的话,默认为删除修改的数据,也就是删除草稿内容。
  5. deleteEnabled: true,使用草案
  6. association [0..1] to C_MM_SupplierValueHelp,是连接到供应商的搜索帮助,在后面字段中注释了的LIFNR中,就会使用此CDS
  7. @Consumption: { valueHelp: ‘_SupplierValueHelp’,filter.mandatory: true }此用于在屏幕中生成一个带必输入的供应商查询条件,可以打开此注释,测试。
  8. @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]用于指定后面的为字节点

1.6元数据扩展层

@Metadata.layer: #CUSTOMER

@UI: {
    headerInfo: {
    typeName: '豁免主控室 typeName',
    typeNamePlural: '豁免主控室 typeNamePlural',
    title: { type: #STANDARD, label: '豁免主控室 title label', value: 'exemption_id' }
    }
}
@UI.presentationVariant: [{
        sortOrder: [{ by: 'last_changed', direction: #ASC }]
}]
annotate view ZACT_C_EXEMPTION with
{
  @UI.facet: [
    {
        label: 'Header data',
        id: 'Header',
        type: #COLLECTION
    },
    {
        label: 'FIELDGROUP_REFERENCE HeaderInfo',
        id : 'HeaderData',
        parentId : 'Header',
        type : #FIELDGROUP_REFERENCE,
        targetQualifier : 'HeaderInfo'
    },
    {
        label: '_ex_chlog',
        purpose: #STANDARD,
        id: '_ex_chlog',
        type: #LINEITEM_REFERENCE,
        targetElement: '_ex_chlog'
    }
  ]
  
  @UI: {
    lineItem: [ 
    -- Action Lineitem  
    { type: #FOR_ACTION, dataAction: 'BOPF:exemption', label: '审批d' }
        //,{ position: 1, importance: #HIGH ,type: #FOR_ACTION,dataAction: 'BOPF:exemption1',label: '审批1'}
        //,{ type: #FOR_ACTION, dataAction: 'BOPF:exemption',label: 'Set CITY_TO' } 
        ],
        identification: [
            {type: #FOR_ACTION,position: 10,dataAction: 'BOPF:exemption',label: '审批' }
            //,{type: #FOR_ACTION,position: 2,dataAction: 'BOPF:prov',label: '审批2' }
             ]
    }
    
    exemption_id;
    
    
    @UI: {
    lineItem: [ 
        { position: 1, importance: #HIGH 
        ,type: #FOR_ACTION,dataAction: 'BOPF:exemption1',label: '审批1'
        }
        //,{ type: #FOR_ACTION, position: 2,dataAction: 'BOPF:exemption1',label: 'Set CITY_TO' } 
        ],
            selectionField: [ { position: 1 } ],
        identification: [
            {position: 1
            //,dataAction: 'BOPF:SET_CITY1',label: '审批', type: #FOR_ACTION
            }
            //,{type: #FOR_ACTION,position: 2,dataAction: 'BOPF:prov',label: '审批' }
             ],
    fieldGroup: [{ qualifier: 'HeaderInfo', position: 1, importance: #HIGH }]
    }
  //审批人
  approver;
  @UI: {
  lineItem: [ { position: 20, importance: #HIGH } ],
  selectionField: [ { position: 20 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 20, importance: #HIGH }]
  }
  //申请人
  applicant;
  @UI: {
  lineItem: [ { position: 21} ],
  identification: [{position: 21}],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 21, importance: #HIGH }]
  }
  //申请人
  appl_comment;
  @UI: {
  lineItem: [ { position: 30, importance: #HIGH ,label:'对象联系人'} ],
  selectionField: [ { position: 30 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 30, importance: #HIGH }]
  }
  //对象提供者
  data_source_id;
  @UI: {
  lineItem: [ { position: 40, importance: #HIGH ,label:'审批状态'} ],
  selectionField: [ { position: 40 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 40, importance: #HIGH ,label:'审批状态'}]
  }

  //审批状态
  prev_state;
  @UI: {
  lineItem: [ { position: 50, importance: #HIGH } ],
  selectionField: [ { position: 50 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 50, importance: #HIGH }]
  }
  //免除状态
  state;
  @UI: {
  lineItem: [ { position: 60, importance: #HIGH } ],
  selectionField: [ { position: 60 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 60, importance: #HIGH }]
  }

  //更改日期(申请人)
  appl_last;
  @UI: {
  lineItem: [ { position: 70, importance: #HIGH } ],
  selectionField: [ { position: 70 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 70, importance: #HIGH }]
  }

  //更改日期(审批者)
  appr_last;
  @UI: {
  lineItem: [ { position: 80, importance: #HIGH } ],
  selectionField: [ { position: 80 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 80, importance: #HIGH }]
  }

  //过期日期
  valid_until;
  @UI: {
  //lineItem: [ { position: 90, importance: #HIGH } ],
  selectionField: [ { position: 90 } ],
  //      identification:[ { position: 20, importance: #HIGH } ],
  fieldGroup: [{ qualifier: 'HeaderInfo', position: 90, importance: #HIGH }]
  }
  //免除原因
  reason;
  //  @UI: {
  //  lineItem: [ { position: 110, importance: #HIGH } ]
  //  }
  //
  //  reason_text;
  @UI: {
  lineItem: [ { position: 110, importance: #HIGH } ]
  //,
  //fieldGroup: [{ qualifier: 'HeaderInfo', position: 100, importance: #HIGH }]
  }

  package_name;
  //  @UI: {
  //  lineItem: [ { position: 120, importance: #HIGH } ]
  //  }
  //
  //  test_title;
  //  @UI: {
  //  lineItem: [ { position: 130, importance: #HIGH } ]
  //  }
  //
  //  msg_title;
  //
  //  @UI: {
  //  lineItem: [ { position: 140, importance: #HIGH } ]
  //  }
  //
  //  package_name;
  //  @UI: {
  //  lineItem: [ { position: 150, importance: #HIGH } ]
  //  }
  //  author;
}

说明:

  1. 在headerInfo中指定很多的抬头信息,具体的内容还在测试中。
  2. @Search.searchable: true //指定主页可以有搜索框,
  3. @Search:{defaultSearchElement: true,fuzzinessThreshold: 0.8}//主页可搜索框可搜索字段,在这里指定的0.8是一个模糊搜索的一个度量,最大是1,由于供应商有前导0,所以用此方法来避免输入供应商前导0来查询。
  4. lineItem,指定在列表中显示的信息,
  5. fieldGroup指定在对像页(细节页)时抬头显示的信息。

其他代码块

@AbapCatalog.sqlViewName: 'YACT_LAST_CHLOG'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'YACT_LAST_SATC_EX_CHLOG'

define view YACT_LAST_SATC_EX_CHLOG
  as select from satc_ci_ex_chlog
{
  key exemption_id      as ExemptionId,
      max ( timestamp ) as Timestamp
     
      
}
group by
  exemption_id

@AbapCatalog.sqlViewName: 'YACT_I_CHLOG'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'YACT_LAST_SATC_EX_CHLOG Basis'


@ObjectModel: {
                updateEnabled: true,
                createEnabled: true,
                deleteEnabled: true,
                semanticKey: ['ExemptionId', 'Timestamp'],
                representativeKey: 'Timestamp',
                writeDraftPersistence: 'ZSD_I_CHLOG_D'
                }
                
define view YACT_I_SATC_EX_CHLOG
  as select from YACT_LAST_SATC_EX_CHLOG as _chlogmax
    inner join   satc_ci_ex_chlog        as _ChlogInfo on  _chlogmax.ExemptionId = _ChlogInfo.exemption_id
                                                       and _chlogmax.Timestamp   = _ChlogInfo.timestamp
  association [1..1] to ZACT_I_EXEMPTION as _exemption on $projection.ExemptionId = _exemption.exemption_id
{

  key _chlogmax.ExemptionId   as ExemptionId,

  key _chlogmax.Timestamp     as Timestamp,


      _ChlogInfo.check_scope  as check_scope,

      _ChlogInfo.chkclass     as chkclass,

      _ChlogInfo.chkcode      as chkcode,

      _ChlogInfo.object_scope as object_scope,

      _ChlogInfo.objname      as objname,

      _ChlogInfo.objtype      as objtype,

      _ChlogInfo.subobjname   as subobjname,

      _ChlogInfo.subobjtype   as subobjtype,

      _ChlogInfo.checksum     as checksum,

      _ChlogInfo.valid_until  as valid_until,

      _ChlogInfo.state        as state,

      _ChlogInfo.applicant    as applicant,

      _ChlogInfo.appl_last    as appl_last,

      _ChlogInfo.reason       as reason,

      _ChlogInfo.appl_comment as appl_comment,

      _ChlogInfo.approver     as approver,

      _ChlogInfo.appr_last    as appr_last,

      _ChlogInfo.appr_comment as appr_comment,
      _ChlogInfo.deleted      as deleted,
      
      @ObjectModel.association: {
              type: [#TO_COMPOSITION_PARENT, #TO_COMPOSITION_ROOT]
          }
      _exemption
}
where
  _ChlogInfo.deleted != 'X' //非删除状态
@AbapCatalog.sqlViewName: 'YACT_SATC_CHLOG'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'YACT检查satc_ci_ex_chlog'
@UI.headerInfo: {
    typeName: '详情',
    typeNamePlural: '计划行',
    title: { type: #STANDARD, label: '豁免主控室详情'}
//    description: {value: 'DefectText'}
}

@VDM.viewType: #CONSUMPTION

@ObjectModel: { updateEnabled: true,
                createEnabled: true,
                deleteEnabled: true,
                semanticKey: ['ExemptionId', 'Timestamp'],
                representativeKey: 'Timestamp' }


define view YACT_SATC_EX_CHLOG
  as select from YACT_I_SATC_EX_CHLOG as _ChlogInfo 
  association [1..1] to ZACT_C_EXEMPTION as _exemption on $projection.ExemptionId = _exemption.exemption_id
{
@UI.facet: [
    {
        label: 'item data',
        id: 'item',
        type: #COLLECTION
    },
    {
        label: 'item HeaderInfo',
        id : 'item HeaderData',
        parentId : 'item',
        type : #FIELDGROUP_REFERENCE,
        targetQualifier : 'HeaderInfo1'
    }
    ]
    @ObjectModel.readOnly: true
      @UI: {
      lineItem: [ { position: 10, importance: #HIGH
                    }
                    
                    ],
                    selectionField: [ { position: 10 } ],
                    fieldGroup: [{ qualifier: 'HeaderInfo1', position: 10, importance: #HIGH }]
                    
      }
    key _ChlogInfo.ExemptionId  as ExemptionId,
    key _ChlogInfo.Timestamp    as Timestamp,
      _ChlogInfo.check_scope  as CheckScope,
      _ChlogInfo.chkclass     as Chkclass,
      @UI: {
        lineItem: [ { position: 30, importance: #HIGH } ],
        selectionField: [ { position: 30 } ],
        identification:[ { position: 30 } ],
        fieldGroup: [{ qualifier: 'HeaderInfo1', position: 30, importance: #HIGH }]
        }
      _ChlogInfo.chkcode      as Chkcode,
      _ChlogInfo.object_scope as ObjectScope,
      @UI: {
            lineItem:[ { position: 20, importance: #HIGH} ],
            selectionField:[ { position: 20 } ],
            identification:[ { position: 20 } ],
            fieldGroup: [{ qualifier: 'HeaderInfo1', position: 20, importance: #HIGH }]
            }
      _ChlogInfo.objname      as Objname,
      
      _ChlogInfo.objtype      as Objtype,
      
      _ChlogInfo.subobjname   as Subobjname,
      
      _ChlogInfo.subobjtype   as Subobjtype,
      
      _ChlogInfo.checksum     as Checksum,
      
      _ChlogInfo.valid_until  as ValidUntil,
      
      _ChlogInfo.state        as State,
      
      _ChlogInfo.applicant    as Applicant,
      
      _ChlogInfo.appl_last    as ApplLast,
      
      _ChlogInfo.reason       as Reason,
      
      _ChlogInfo.appl_comment as ApplComment,
      
      _ChlogInfo.approver     as Approver,
      
      _ChlogInfo.appr_last    as ApprLast,
      _ChlogInfo.appr_comment as ApprComment,
      _ChlogInfo.deleted      as Deleted,
      
      //Assocation      
          @ObjectModel.association: {
            type: [#TO_COMPOSITION_PARENT, #TO_COMPOSITION_ROOT]
        }
    _exemption
}
@AbapCatalog.sqlViewName: 'ZDDL_I_CONTACTS'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '豁免主控室 satc_ac_contacts'

//@VDM.viewType: #CONSUMPTION
//@ObjectModel: { updateEnabled: true,
//                createEnabled: true,
//                deleteEnabled: true,
//                semanticKey: ['object', 'obj_name','system_group'],
//                representativeKey: 'object',
//                writeDraftPersistence: 'ZSD_CONTACTS_D' }
                
                
define view ZACT_I_SATC_AC_CONTACTS as select from satc_ac_contacts
//association [1..1] to ZACT_I_EXEMPTION    as _exemption    on  $projection.object     = _exemption.objtype
//                                                               and $projection.obj_name     = _exemption.objname
//                                                               and $projection.system_group = _exemption.ds_group_id
{
    key object,
    key obj_name,
    key system_group,
    author,
    @ObjectModel.readOnly
    package_name,
    changed_on,
    xx_hint
//    _exemption
    
}

总结

  1. 当修改了CDS后,特别是BOPF后,如一些功能发现不正常,可以考虑删除BOPF及及相关的所有类,表,重新激活CDS来生成BOPF及相关内容。
  2. 当修改CDS,及注释后,在前端没反映出修改的内容,可以重新生成ODATA,或者SEGW重生对应的项目,同时使用事务码:/n/IWFND/CACHE_CLEANUP清除缓存。
  3. 由于做CDS时,我们一开始经常什么变更字段,表等,或者需求的变化,而CDS会自动生成很多东西,特别是BOPF的相关的东西,很多会自动生成,但由于CDS的变更,特别是字段的这些变更能够自动更新,所以会导致各种错误,这里的解决法办,可能是删除相关自动生成的对像,如你准确知道应该要删除什么对像那可直接删除,但事实中我们总是判断不了要删除那些自动生成的对像,所以我都是删除所有自动生成的对像,为此我们最好把一个业务相关的CDS创建到一个包里,这里可能会更方便删除。
  4. 在主从视图关联激活时,需要两个视图同时一起激活。
  5. 在激活时,最好当前显示的只是需要激活的对像,不然,激活时会判断已打开的是否能激活(就算没选中也会去激活),这样报错不一定是你当前对像的报错。

2.激活和增强

2.1 Eclipse中直接开发

数据消费层加入注解@OData.publish: true ,然后直接激活服务(见2.4)

2.1.1 绑定action

通过注解的dataAction把ID绑定到一个名为'exemption'的Action上,按钮名称为'审批d'

@UI: {
    lineItem: [
    -- Action Lineitem
    { type: #FOR_ACTION, dataAction: 'BOPF:exemption', label: '审批d' }
        ]
    }

  exemption_id;



#如果写法为:dataAction: 'exemption',需要为cds 创建Behavior Definition,并定义action

    action ( features: instance ) exemption result [1] $self;
    #在特定字段发生变化并保存时触发校验逻辑,字段名称维护在大括号内。
    validation validateExemption on save { field exemption_id; }
    validation validateDates on save { field begin_date, end_date; }

 在bopf中增加方法

SAP CDS 开发和Fiori App生成学习笔记_第4张图片

SAP CDS 开发和Fiori App生成学习笔记_第5张图片

SAP CDS 开发和Fiori App生成学习笔记_第6张图片

 

class ZCL_ACT_A_EXEMPTION definition
  public
  inheriting from /BOBF/CL_LIB_A_SUPERCL_SIMPLE
  final
  create public .

public section.

  methods /BOBF/IF_FRW_ACTION~EXECUTE
    redefinition .
protected section.
private section.
ENDCLASS.



CLASS ZCL_ACT_A_EXEMPTION IMPLEMENTATION.


  method /BOBF/IF_FRW_ACTION~EXECUTE.
DATA(lt_data) = VALUE ZTACT_I_EXEMPTION1( ).
    DATA: ls_msg       TYPE symsg,
          lv_dummy_msg TYPE string.
    "Read UI clicked sale order
    io_read->retrieve(
      EXPORTING
        iv_node                 =  is_ctx-node_key   " BO Node Name
        it_key                  =  it_key            " BO Key
      IMPORTING
        et_data                 =  lt_data ).   " Data Return Structure

    "Assuming single instance for a action
    eo_message = /bobf/cl_frw_factory=>get_message( ) .
    LOOP AT lt_data ASSIGNING FIELD-SYMBOL().

      -OBJNAME = 'TEST'.

      IF -PREV_STATE <> 'APPR'.
        "Now update the BO instance
        io_modify->update(
          EXPORTING
            iv_node           = is_ctx-node_key    " Node
            iv_key            = -key    " Key
            iv_root_key       = -root_key     " NodeID
            is_data           = REF #( -node_data )    " Data
            it_changed_fields = VALUE #(
                                ( zif_z_i_fly_c=>sc_node_attribute-zz_i_fly-cityto ) )
                        ).

        ls_msg = VALUE #( msgty = 'S' msgid = '00' msgno = '001'
                          msgv1 = |{ -EXEMPTION_ID }/{ -PREV_STATE }| msgv2 = '成功' ).
        eo_message->add_message(
          EXPORTING
            is_msg       =  ls_msg   " Structure of Message Variables
            iv_node      =  is_ctx-node_key   " Node Name
            iv_key       =  -key   " Key
*                   iv_lifetime  =  /bobf/cm_frw=>co_lifetime_state
            ).
      ELSE.
        ls_msg = VALUE #( msgty = 'E' msgid = '00' msgno = '001'
                          msgv1 = |{ -EXEMPTION_ID }/{ -PREV_STATE }| msgv2 = '失败' ).
        eo_message->add_message(
          EXPORTING
            is_msg       =  ls_msg   " Structure of Message Variables
            iv_node      =  is_ctx-node_key   " Node Name
            iv_key       =  -key   " Key
*           iv_lifetime  =  /bobf/cm_frw=>co_lifetime_state
            ).
        APPEND VALUE #( key = -key ) TO et_failed_key .
      ENDIF.
    ENDLOOP.
*    IF -carrid = 'AA'.
**      MESSAGE S000(zyk_cm_bus_plan) WITH 'THIS IS ANOTHER!' INTO lv_dummy_msg.
**      MOVE-CORRESPONDING sy TO ls_msg.
**       eo_message->add_message(
**         EXPORTING
**           is_msg       =  ls_msg   " Structure of Message Variables
**           iv_node      =  is_ctx-node_key   " Node Name
**           iv_key       =  -key   " Key
***           iv_lifetime  =  /bobf/cm_frw=>co_lifetime_state
**           ).
**       APPEND VALUE #( key = -key ) TO et_failed_key .
*    ENDIF.
*    IF eo_message IS BOUND .
*      eo_message = /bobf/cl_frw_factory=>get_message( ) .
*    ENDIF.
  endmethod.
ENDCLASS.

 2.1.2 效果展示SAP CDS 开发和Fiori App生成学习笔记_第7张图片

2.2 BOPF方式

找到转换层生成的BOPF(TCODE:BOBF/BOBX)

​ 

 2.2.1 BOPF里面ACTION的实现

SAP CDS 开发和Fiori App生成学习笔记_第8张图片

2.2.2使用(tcode:BOBT)测试ACTION

SAP CDS 开发和Fiori App生成学习笔记_第9张图片

SAP CDS 开发和Fiori App生成学习笔记_第10张图片

SAP CDS 开发和Fiori App生成学习笔记_第11张图片

2.2.3 BOPF里面Validations的实现

Validations和action类似需要创建实施类,Trigger Action勾选Action就会触发校验

SAP CDS 开发和Fiori App生成学习笔记_第12张图片

2.2.4 BOPF里面Query的实现

SAP CDS 开发和Fiori App生成学习笔记_第13张图片

 SAP CDS 开发和Fiori App生成学习笔记_第14张图片

2.2.5 激活oData服务(见2.4)

2.3 事务码SEGW创建ODATA 服务

2.3.1 事务码SEGW创建ODATA 服务

登陆SAP GUI 后,使用事务码SEGW,创建一个SAP Gateway Service Builder,在此定义为了ZTEST.

SAP CDS 开发和Fiori App生成学习笔记_第15张图片

创建成功后,就生成了一个ODATA工程对像ZTEST,此工程中可引入多个表,或者多个定义的CDS,下面以引入前文创建的CDS为例。

SAP CDS 开发和Fiori App生成学习笔记_第16张图片

2.3.2 引入CDS到ODATA中

在ZTEST工程下,“Odata Model”上点击右键,选择Reference->Data source,

SAP CDS 开发和Fiori App生成学习笔记_第17张图片

在其中输入前文中创建的DDL Source名字:ZTEST01(与CDS同名)。

SAP CDS 开发和Fiori App生成学习笔记_第18张图片

点击完成后,生成如图的CDS-Entity exposures

SAP CDS 开发和Fiori App生成学习笔记_第19张图片

 激活ODATA项目工程,点击“Generate Runtime Objects”,此步骤,一定要先选择工程项目(ZTEST),否则激活时会报错的。成功后如图。

SAP CDS 开发和Fiori App生成学习笔记_第20张图片

2.3.3 激活oData服务(见2.4)

2.3.4对ODATA进行增强

激活过后可以看到Runtime那里可以展开了
SAP CDS 开发和Fiori App生成学习笔记_第21张图片
选择DPC_EXT
SAP CDS 开发和Fiori App生成学习笔记_第22张图片
DPC:data provider class CRUD的地方
MPC:modle provider class 数据提供的地方

进去后,下拉找到get_entityset
SAP CDS 开发和Fiori App生成学习笔记_第23张图片
双击get_entityset,进入到方法内部,然后把里面的代码复制
SAP CDS 开发和Fiori App生成学习笔记_第24张图片
然后返回到上一页面,选择get_entityset,点击左上角更改,然后点击重新定义方法
SAP CDS 开发和Fiori App生成学习笔记_第25张图片
进入方法体后,把里面的替换为上面复制的
SAP CDS 开发和Fiori App生成学习笔记_第26张图片
然后添加写上自己的代码,最后激活
SAP CDS 开发和Fiori App生成学习笔记_第27张图片
(为什么需要这样重新定义方法,而不是在上一步进入get_entityset里面后直接去点击更改,然后写代码 ?第一种:点击重新定义方法,这个方法就会变色,见下图,很容易看出来这个方法做了增强。第二种:如果在get_entityset方法体里面直接点击更改,然后写代码,这个方法是不会变色的,看不出来对哪个方法做了增强。两种除了这个差别,两者最终能实现的的效果其实都一样)
SAP CDS 开发和Fiori App生成学习笔记_第28张图片
 

 2.4激活ODATA服务

运行事务码:/IWFND/MAINT_SERVICE 打开激活服务功能,如运行此事务码报错:“用户不能再登陆”,如图。可以在此事务码前面加/n,也就是:/N/IWFND/MAINT_SERVICE 来打开,或者直接在SE93中打开,或者把此事务码添加到收藏菜单中,就不会报错了。

SAP CDS 开发和Fiori App生成学习笔记_第29张图片

打开后,点击添加服务

SAP CDS 开发和Fiori App生成学习笔记_第30张图片

在此输入系统别名:LOCAL,技术服务名称,输入前面SEGW创建的工程名:ZTEST*(或者CDS名称),找到SAP CDS 开发和Fiori App生成学习笔记_第31张图片
SAP CDS 开发和Fiori App生成学习笔记_第32张图片
SAP CDS 开发和Fiori App生成学习笔记_第33张图片
然后返回上一页面,找到自己的服务ZTEST_SRV服务,选择,并点击“添加所选服务”。

SAP CDS 开发和Fiori App生成学习笔记_第34张图片

输入开发包,点击确认保存,

SAP CDS 开发和Fiori App生成学习笔记_第35张图片

2.5删除服务

先删除“系统别名”,然后再删除“ Internet 通信框架 ”,最后就能正常的删除ODATA的服务了。

SAP CDS 开发和Fiori App生成学习笔记_第36张图片

3.根据模板创建Fiori应用

SAP CDS 开发和Fiori App生成学习笔记_第37张图片

 SAP CDS 开发和Fiori App生成学习笔记_第38张图片

这一步要填写app信息,慎重填写(不要学我乱填)

SAP CDS 开发和Fiori App生成学习笔记_第39张图片​ 选择刚刚激活的CDSSAP CDS 开发和Fiori App生成学习笔记_第40张图片

 全选SAP CDS 开发和Fiori App生成学习笔记_第41张图片

 选择主页面,点击完成SAP CDS 开发和Fiori App生成学习笔记_第42张图片

4.效果

4.1运行

SAP CDS 开发和Fiori App生成学习笔记_第43张图片

4.2效果

主页

SAP CDS 开发和Fiori App生成学习笔记_第44张图片

 点击进入详情页

SAP CDS 开发和Fiori App生成学习笔记_第45张图片

你可能感兴趣的:(sap,Fiori,学习,fiori,sap,CDS)