什么是SAP GUI的client

我们用SAPGUI登录某个系统时,除了用户名和密码外,还要指定一个必填字段client:这个client是什么东东?看文档:SAP Client is the highest hierarchical organizational unit within an SAP system that contains master records and tables. The transactions processed at SAP client level is valid and applicable for all company code data and enterprise structures.Client is a three digits numerical key and from a business point of view, client represents as a corporate group. User is required to enter client key while logging on to the SAP system.SAP client是SAP系统里包含了主数据和业务数据的层级结构最高的组织单元标识符,业务上来说代表一个企业,技术类型是一个三位的正整数。Important Client CharacteristicsEvery SAP user’s access and authorizations must assigned to the SAP client on which client users are working.It is used to differentiate between development, quality and product system within the same or different serverThe data entered at client level is valid for all organizational units.Each client can have one or more company codes, plants and locations but there will be not have connection between clients.事务码SCC4查看Netweaver系统上所有已创建的client列表:要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

S/4HANA生产订单增强WORKORDER_UPDATE方法BEFORE_UPDATE参数分析

题目这个增强的输入参数很恐怖,长长的一串: CALL BADI l_badi->BEFORE_UPDATE EXPORTING IT_PIINSTRUCTIONVALUE = IT_PIINSTRUCTIONVALUE IT_PIINSTRUCTION = IT_PIINSTRUCTION IT_PMPARTNER_OLD = IT_PMPARTNER_OLD IT_PMPARTNER = IT_PMPARTNER IT_PRT_ALLOCATION_OLD = IT_PRT_ALLOCATION_OLD IT_PRT_ALLOCATION = IT_PRT_ALLOCATION IT_DOCLINK_OLD = IT_DOCLINK_OLD IT_DOCLINK = IT_DOCLINK IT_OPR_RELATIONS_OLD = IT_OPR_RELATIONS_OLD IT_OPR_RELATIONS = IT_OPR_RELATIONS IT_STATUS_OLD = IT_STATUS_OLD IT_STATUS = IT_STATUS IT_PLANNED_ORDER = IT_PLANNED_ORDER IT_MILESTONE_OLD = IT_MILESTONE_OLD IT_MILESTONE = IT_MILESTONE IT_PSTEXT_OLD = IT_PSTEXT_OLD IT_PSTEXT = IT_PSTEXT IT_RELATIONSHIP_OLD = IT_RELATIONSHIP_OLD IT_RELATIONSHIP = IT_RELATIONSHIP IT_COMPONENT_OLD = IT_COMPONENT_OLD IT_COMPONENT = IT_COMPONENT IT_OPERATION_OLD_AFVU = IT_OPERATION_OLD_AFVU IT_OPERATION_OLD_AFVV = IT_OPERATION_OLD_AFVV IT_OPERATION_OLD_AFVC = IT_OPERATION_OLD_AFVC IT_OPERATION = IT_OPERATION IT_SEQUENCE_OLD = IT_SEQUENCE_OLD IT_SEQUENCE = IT_SEQUENCE IT_ITEM_OLD = IT_ITEM_OLD IT_ITEM = IT_ITEM IT_HEADER_OLD = IT_HEADER_OLD IT_HEADER = IT_HEADER.好在绝大部分内表都是空的。我们就一起来看看非空列表里包含的数据。IT_STATUS状态迁移。STAT是SAP系统状态ID,其描述信息在表TJ02T里能查到。比如I0001状态的四位标识符是CRTD,意思是已创建-CreatedINACT栏为X的状态代表该Production Order当前已经从该状态跳转到了其他状态。上图的意思是该Production Order已经从状态I0001已创建,进入了状态I0002- Released已释放。IT_COMPONENT要理解Production Order component这个概念,我们先看一个已经创建好的生产订单。下图component的意思是为了生产REDUCER_A这个成品,我们需要生产它的组件0010 COVER1, 0020 AXIS和0030 BASE。那么REDUCER_A和其三个组件运行时的信息,就维护在内表IT_COMPONENT里。IT_OPERATION同理,一个生产订单可以包含若干生产工序,比如下图的Manual processing, Maching,Assembly和Testing,对应的系统状态都是REL - Released。这些工序信息维护在内表IT_OPERATION里IT_SEQUENCE该生产订单的前置文档信息,即我们说的文档流 - document flowIT_ITEM待生产的成品明细,比如物料主数据ID,待生产数量,单位等。IT_HEADER很好理解,生产订单抬头信息:要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

SAP R/3系统的R和3分别代表什么含义,负载均衡的实现原理

1972年,SAP诞生,推出了RF系统(实时财务会计系统), 后来命名为R1。R指Real time。3既指第三代系统,又代表3层架构。三层架构分别为下图的Presentation server Layer,Application server layer和Database server layer。值得一提的是,时光之轮已经驶入了2019年的猪年,presentation server层除了上图传统的SAPGUI外,也支持其他的技术:ABAP In EclipseABAP in WebIDEABAP in Visual Studio Code在我 微信公众号“汪子熙”里曾经发表过一篇公众号文章:那些年我用过的SAP IDE里面介绍过上述提到的不同的presentation layer(展现层)的实现技术。下图是在Eclipse里进行ABAP开发:在浏览器里进行ABAP开发:在微软的Visual Studio Code里开发:再看中间的应用服务器层:这里能看出应用服务器层是支持负载均衡的,SAPGUI的使用者会指定消息服务器Message Server的地址,用户通过SAPGUI登录时,消息服务器会将用户请求分配到负载最小的应用服务器实例上。下图含义为在任意一个SAP系统的服务器实例里,使用事务码SM51都可以查看该系统所有的应用服务器实例。而数据库服务器的实例,从菜单System-Status里可以得到。SAP Netweaver 应用服务器可以连接多个数据库,每个数据库可以来自不同的数据库提供商。使用事务码DBCO在Netweaver应用服务器上维护指向数据库服务器的连接明细:从DBMS这个字段能得到所有NetWeaver支持的数据库服务器,比如MaxDB,Infomix,微软的SQL Server,Oracle DB等。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 14, 2019 · 1 min · jiezi

SAP S/4HANA生产订单创建时使用的工厂数据是从什么地方带出来的

大家如果使用我github上的这段代码创建S/4HANA的生产订单时,一定会发现,我在代码里并没有硬编码来指定生产订单的ID,然而运行时会发现我在系统里配置的这个2800被自动使用了,这是怎么做到的呢?https://github.com/i042416/Kn…通过阅读SAP S/4HANA有关生产订单的标准代码发现,生产订单使用的plant工厂数据来自表VBAP的字段WERKS。FV45EFMA_VBAP正是销售订单的行项目表。问题就转化为这个2800和销售订单行项目的关系。这个2800来自结构体KUWEV的字段DWERK Delivering Plant:Ship-to Party’s View of the Customer Master RecordFV45PF0K_KOMKG_KOMPG_FUELLEN,第45行。第32行重要的函数 RV_CUSTOMER_MATERIAL_READDA_KUNNR:这个字段存放的是我代码里硬编码的这个客户ID:VBAK-VKORG:VBAK-VKORGVTWEG: distribution channelSPART: division然后通过函数LOCATION_ISS_PLANT_DETERMINE决定出plant:从这里能看出这个plant来自客户主数据的ship to 视图:kuwev KUWEV-DWERKkuwev的值从哪里来?从KNVV的字段VWERK里来:knvv是客户主数据的Sales data存储表:如何查看S/4HANA里的客户主数据的Sales相关数据?事务码BP:根据客户ID搜索之后,在明细页面里将Display in BP role的下拉菜单宣称FLCU01 Customer:点这个Sales and distribution按钮:2800就维护在这里的:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 3, 2019 · 1 min · jiezi

一些通过SAP ABAP代码审查得出的ABAP编程最佳实践

这两个IF ELSE分支里检测的条件其实逻辑上来说都是同一类,应该合并到一个IF分支里进行检查:It is an expensive operation to open a file in application server with 50MB file size.Current logic is:1. Open the file in application server2. Read the file content line by line3. If the file is regarding IPG or MIDH or TPG, handle with each line separatelyThe correct logic should be:1. Check the file path whether it is IPG or MIDH or TPG related. If not, quit the report.2. Handle with each line directly without evaluate file path in the BIG loop.The validation logic for input records should be improvedLoop at all service BOM, check whether the ID in current loop does exist in validation table lt_valid_prod or lt_valid_sp. If so, delete them via DELETE TABLE XXX FROM <current line>.Improvement: use DELETE XXX WHERE product_id NOT IN <range table>. It is more efficient when lt_srv_bom_file has a huge number of records. See comparison below ( unit: second )这是一个性能问题。使用ABAP原生支持的NOT IN关键字可以获得更好的性能。性能评测如下:Avoid using SELECT to access table with a large number of entriesIn product / IObject area, the best practice is to use OPEN CURSOR / FETCH NEXT CURSOR to access big DB table.如果需要用ABAP OPEN SQL读取一张包含海量记录的数据库表,那么推荐使用OPEN CURSOR进行分块读取。Although this solution will spend almost the same time to fetch the data from DB, it has far less memory consumption compared with using SELECT to fetch ALL data from DB at one time.The original dump due to out of memory issue could be eliminated by replace SELECT with OPEN CURSOR statement.这种方式和直接用SELECT相比,能显著减少内存消耗量。使用并发编程提高应用程序场景通过下面这段代码模拟一个费时的ABAP程序:定义一个ABAP函数:这个函数里执行一大堆计算,然后把传入的product ID写到一张自定义表ZJERRY1里。调用这个函数的代码:注意第二种方案使用STARTING NEW TASK达到的并发执行效果:通过比较,第二种解决方案的效率是第一种的四倍。1. The more CPU & DB time spent in ZINSERT, the better performance will be gained by usingparallel processing (Asynchronous RFC call).2. The more number of ZINSERT call, the better performance will be gained by using parallelprocessing.要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 3, 2019 · 2 min · jiezi

SAP HANA Delivery Unit概念简述

介绍在SAP HANA应用开发领域里,我们通常用package来存储modeler views和XS工程等模型。这些包应该被部署到最终的生产服务器上。Delivery Unit是SAP HANA原生开发对象的部署方式,可以被看成一系列包的集合,用于Transportation management的统一管理。SAP HANA提供了一个统一的管理平台,称为HANA Application Lifecycle Management来管理Delivery Unit. 只有具有权限“sap.hana.xs.lm.roles: :Administrator”的用户才能操作Delivery Unit。 下面介绍操作Delivery Unit的两种方式。SAP HANA Studio选择右键菜单里的Transport Management:直接使用具有下列命名规范的url:http://&lt;host_address>:80<instance_number>/sap/hana/xs/lm/index.html我们能用HANA Application Lifecycle Management做哪些事情?导入/导出/创建Delivery unit,搜索包。 第一次使用HANA Application Lifecycle Management时,我们必须提供一个Vendor ID。Delivery Unit的创建页面:在SAP HANA SP07里, HANA安装完毕后,系统会自动创建一些delivery unit,位于PRODUCTS->Delivery Units下面. 我们可以在里面增加,删除或者更改Delivery Unit。Delivery Unit本身的创建操作是很简单的:将包分配给这个Delivery Unit:Delivery Unit和里面包含的包可以通过下面的菜单导出成.tgz文件:导入Delivery Unit时,其包含的包会在HANA实例上创建:SAP HANA Studio提供了DU的管理控制台,切换到modeler视图,选择Setup下面的Delivery Unit进入控制台:创建DU,给其分配包:导入/导出DU:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 3, 2019 · 1 min · jiezi

SAP S/4HANA生产订单的BAdI增强点之Initialize方法

在S/4HANA里创建生产订单时,有一个增强点WORKORDER_UPDATE:这个CAUFVDB里存放的是生产订单抬头级别的数据:我们来观察下运行时这个结构里存放的数据。请大家用我github上这个简单的报表创建一个生产订单:https://github.com/i042416/KnowlegeRepository/blob/master/ABAP/SmallApp/209_create_S4_SalesOrder.abap断点触发后,结构体CAUFVDB里的字段,我们一个一个分析:AUFNR: 这个字段代表生产订单的ID,因此此时还没有保存,所以是临时ID。WERKS 工厂ID plant ID,2800。DISPO MRP controller for the order:001PVERW: 1在表T411里发现1代表Production:PLNBEZ:待生产的物料主数据IDPLNAW: Application of the task listP的含义,在表TCA09里找到代表Routings for productionPLNTY:Task list type: N在表TCA01里代表routingPLNNR:Key for Task List Group50000023PLNAL: Group counterPDATV: valid from dateAUFLD: Date of BOM Explosion/Routing TransferAUFPL: Routing number of operations in the orderRSNUM: Number of reservation/dependent requirementsGAMNG: Total Order Quantity 要生产的产品个数GMEIN: 生产的产品的单位TERKZ: 2 - scheduling type2在表T482里的类型是backwards schedulingAUART: 生产订单类型 PP04AUTYP:生产订单category:10 PP Production OrderBUKRS: company codeKAPPL:application code KA条件技术表里KA代表OrdersKALSM:PP-PC1 costing sheetZAEHL和MZAEHL都是内部计数器KLVARP:Costing Variant for Planned CostsKLVARI:Costing Variant For Actual CostsSFCPF:Production Scheduling Profile 这个SIA是我自己配的。AVOUEB:布尔值,Indicator: Display operation overviewFLG_TERM: 布尔值,Indicator: Scheduling must take data changes into accountTYPKZ: 1 Category of object causing the load (order category)代表Work orders (detailed scheduling / routing…)AUKBED:Indicator: Calculate capacity requirements 布尔值要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 3, 2019 · 1 min · jiezi

SAP S/4HANA销售订单创建时,会自动触发生产订单的创建

这个自动触发的过程是怎么实现的?使用下面的代码创建一个销售订单:DATA: ls_header TYPE bapisdhd1, ls_headerx TYPE bapisdhd1x, lt_bapiret2 LIKE bapiret2 OCCURS 0 WITH HEADER LINE, po_order_number TYPE bapivbeln-vbeln, lt_partners TYPE TABLE OF bapiparnr, lt_order_items_in TYPE TABLE OF bapisditm, lt_order_item_x TYPE TABLE OF bapisditmx, ls_order_item_x LIKE LINE OF lt_order_item_x, ls_order_items_in LIKE LINE OF lt_order_items_in, lt_schdlin TYPE TABLE OF bapischdl, ls_schdlin LIKE LINE OF lt_schdlin, lt_schdlinx TYPE TABLE OF bapischdlx, ls_schdlinx LIKE LINE OF lt_schdlinx, ls_partners LIKE LINE OF lt_partners, lt_order_text TYPE TABLE OF bapisdtext, ls_order_text TYPE bapisdtext.ls_header-serv_date = ‘20200101’.ls_header-doc_type = ‘TA’.ls_header-purch_no_c = ‘a’.ls_headerx-purch_no_c = ‘X’.*ls_header-sales_org = ‘0001’.*ls_header-distr_chan = ‘01’.ls_header-division = ‘01’.ls_header-comp_cde_b = ‘0001’.ls_headerx-comp_cde_b = ‘X’.ls_headerx-doc_type = ‘X’.ls_headerx-updateflag = ‘I’.ls_partners-partn_role = ‘WE’. “ship to partyls_partners-partn_numb = ‘0000000001’.APPEND ls_partners TO lt_partners.ls_partners-partn_role = ‘AG’. " sold to partyls_partners-partn_numb = ‘0000000001’.APPEND ls_partners TO lt_partners.ls_order_items_in-item_categ = ‘TAN’.ls_order_items_in-material = ‘REDUCER_A’.ls_order_items_in-target_qty = 999.ls_order_items_in-itm_number = 10.ls_order_item_x-item_categ = ‘X’.ls_order_item_x-material = ‘X’.ls_order_item_x-target_qty = ‘X’.ls_order_item_x-itm_number = ‘X’.ls_order_item_x-updateflag = ‘I’.APPEND ls_order_item_x TO lt_order_item_x.APPEND ls_order_items_in TO lt_order_items_in.ls_schdlin-itm_number = 10.ls_schdlin-req_qty = 3.ls_schdlinx-itm_number = ‘X’.ls_schdlinx-itm_number = ‘X’.ls_schdlinx-updateflag = ‘X’.APPEND ls_schdlin TO lt_schdlin.APPEND ls_schdlinx TO lt_schdlinx.“ls_order_text-doc_number = SALESDOCUMENT.ls_order_text-itm_number = ‘000010’.ls_order_text-text_id = ‘0006’.“ls_order_text-langu = ‘E’.ls_order_text-langu_iso = ‘ZH’.ls_order_text-format_col = ‘’.ls_order_text-text_line = ‘Test 2 DSFSDFDSFDS’.ls_order_text-function = ‘006’.APPEND ls_order_text TO lt_order_text.CALL FUNCTION ‘SD_SALESDOCUMENT_CREATE’ EXPORTING sales_header_in = ls_header sales_header_inx = ls_headerx int_number_assignment = ‘X’ IMPORTING salesdocument_ex = po_order_number TABLES return = lt_bapiret2 sales_items_in = lt_order_items_in sales_items_inx = lt_order_item_x sales_schedules_in = lt_schdlin sales_schedules_inx = lt_schdlinx sales_partners = lt_partners sales_text = lt_order_text.LOOP AT lt_bapiret2 ASSIGNING FIELD-SYMBOL(<return>) WHERE type = ‘E’. WRITE:/ ‘Error:’, <return>-message COLOR COL_NEGATIVE. RETURN.ENDLOOP.IF po_order_number IS INITIAL. WRITE:/ ‘PO number initial’. RETURN.ENDIF.CLEAR: lt_bapiret2.CALL FUNCTION ‘BAPI_TRANSACTION_COMMIT’ EXPORTING wait = ‘X’ IMPORTING return = lt_bapiret2.LOOP AT lt_bapiret2 ASSIGNING <return>. WRITE:/ ‘Message:’, <return>-message COLOR COL_POSITIVE.ENDLOOP.用事务码SAT分析,发现总共创建消耗的时间为3.98秒,其中1.84秒花费在EIGENFERTIGUNG_BEARBEITEN这个subroutine上。用一下Google Translate:发现EIGENFERTIGUNG的含义就和生产有关:own productionBEARBEITEN的意思是TO eidt:看这个函数CO_61_ORDER_EDIT:这个函数的描述信息指向了它是用来做生产用的:这个函数所在的包也透露了它的作用,是负责生产相关实现的:观察一下传入这个函数的各参数值:要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

February 3, 2019 · 2 min · jiezi

如何在SAP C4C里使用ABSL消费第三方Restful API

首先我们得有一个可以正常工作的Restful API:然后在Cloud for Customer的Cloud Application Studio里创建Restful API的模型,把第一步可以正常工作的Restful API url填进模型里去:然后在ABSL里使用如下代码进行消费:import ABSL;if( this.OutboundDeliveryID.IsInitial() == false){ raise already_delivered.Create(“E”); return;}var HttpMethod = “GET”;var HttpResource = “”; // not requiredvar ContentType = “”; // not requiredvar Body = “”; // not requiredvar HeaderParameter : collectionof NameAndValue; // not requiredvar URLParameter : collectionof NameAndValue;var URLParameterEntry : NameAndValue;URLParameterEntry.Name = “SoID”;URLParameterEntry.Value = this.ID.content;URLParameter.Add(URLParameterEntry);var response = WebServiceUtilities.ExecuteRESTService(“JerryExternalService”, “JerryExternal”, HttpMethod, HttpResource,URLParameter, HeaderParameter,ContentType, Body);this.OutboundDeliveryID = response.Content;raise delivery_message.Create(“S”, this.OutboundDeliveryID);要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 3, 2019 · 1 min · jiezi

SAP UI5和微信小程序对比之我见

今天继续由SAP成都研究院著名的菜园子小哥Wang Cong,给大家分享他作为一个SAP前端人员是如何看待SAP UI5和微信小程序的异同点的。关于Wang Cong种菜的手艺,大家请移步到他以前的文章 SAP成都研究院非典型程序猿,菜园子小哥:当我用UI5诊断工具时我用些什么 去观摩,这里不再赘述。下面是他的正文。*近几年微信小程序发展之势如火如荼,越来越多的用户放弃原生App,转而投入小程序的怀抱,大有"一个微信行天下"的趋势。面对如此巨大的流量机遇,百度、阿里等公司也纷纷在自家的核心产品中推出小程序功能,欲与腾讯的微信在这场入口大战中一较高下。至少在今天看来,微信小程序的生态圈依然是其中最为繁荣的。同为"前端框架",SAP UI5与微信小程序有着诸多异同点。这里我们摘取其中本人觉得比较有特点的方面进行对比,看看二者相似的表象下隐含着哪些设计理念上的区别。本文仅代表作者个人作为一个前端开发人员的个人观点。UI5是SAP开发的一套开源的前端框架,而微信小程序则是局限在微信内部,表现形式类似于普通App。虽然两者的核心(或者说大部分功能)都是与用户进行交互,但从架构的角度看,存在很多本质上的不同,我们可以从接口的角度窥见一二。入口UI5不依托任何平台,通过UI5实现的页面可以从多种入口进行访问,基本上只要支持浏览器功能的平台,都可以访问UI5页面。而微信则是微信小程序的唯一入口。后端UI5是一个纯粹的前端框架,对于后端没有做任何的限制,同时也没有任何的支持。微信小程序不但允许你自由地选择后端,而且提供了一些基础的后端支持,在很多情况下开发者甚至无需搭建自己的服务器,就能满足需求。这些支持有:(1) 数据库:微信小程序提供远端的类似MongoDB的JSON数据库支持,用户不需要购买数据库,也不需要任何复杂的前期配置,就能在小程序中直接对JSON数据库进行增删查改等操作。(2) 存储:类似于上面提到的JSON数据库,用户可以在微信小程序中直接利用免费且免配置的远端存储空间来存储文件。(3) 云函数:除了数据库和存储之外,微信小程序还提供了后端逻辑的支持。云函数可以理解成一个功能有限的后端服务器,也可以理解成一个运行在云端的JavaScript方法。优点是方便,一键部署而且免费。缺点是功能有限,无法实现复杂的后端功能。以上功能全部免费免配置,如果发现免费的配额不够,可以申请提升配额或考虑自己搭建服务器。访问限制作为开放的框架,UI5对于外部访问没有做任何限制。而微信小程序则有着严格的审核机制,首先要访问的链接必须是https的安全链接,其次地址必须提交给微信进行审核,审核过后还需维护在小程序后台的访问列表当中。如果上述步骤没有做好,就连腾讯自己的官网都无法访问。其实这样做的原因也很容易理解:用户通过微信小程序访问的所有链接,最初的入口都是微信本身,这也是微信为了自身生态安全而做的必要控制。但这项限制在本文发稿时为止还不是特别完善。因为云函数尚未对访问做限制,开发者可以使用云函数作为路由,访问未经审核的链接。从上面和下面两张图中我们可以看出UI5应用和微信小程序在接口方面的区别,其中虚线框内分别为UI5和微信小程序框架内所提供的功能范围。技术细节一个熟悉SAP UI5的前端开发人员,上手微信小程序应该没有什么难度。两者同为前端框架在设计上自然有很多相似的地方。例如:(1) 在微信小程序中的app.js极其类似于UI5中的component.js,都代表整个应用的一个全局实例。某些作用范围为全局的方法或数据都可以存于其中。(2) 两者在数据绑定方面,都支持灵活的表达式绑定,将更多的本应出现在controller层的逻辑向前推放到view层当中,简化逻辑层。(3) 两者都支持列表渲染,例如UI5中的ListBase中的items属性,而微信小程序中则是通过wx:for属性实现同样的功能。(4) 两者都支持自定义控件/模板,UI5有component和custom control,微信小程序有component和template。但两者也有很多技术上的区别,例如:(1) 前文提到的列表渲染,UI5仅支持对列表类控件的子控件进行列表渲染。而微信小程序则显得更加灵活一些,任何一个控件都可以通过wx:for属性进行重复渲染。例如上面例子中被重复渲染的就是image元素。(2) 除了列表渲染,微信小程序更支持wx:if的条件渲染。即if条件检测的结果为true时渲染,为false时则忽略。UI5中实现类似功能则更多是通过控制visible属性来进行。(3) Routing的实现。两者都是使用栈的方式记录跳转的历史,但是与UI5的"宽容"不同,微信小程序最多仅支持5层跳转。如用户需要继续向下访问,则必须通过其他workaround实现,例如通过redirectTo将栈顶的旧页面弹出栈,换成新页面。(4) 数据绑定方面。UI5的数据绑定功能极其强大,支持各种类型的数据模型的排序和筛选,并且提供双向绑定和单向绑定多种绑定方式。另外数据在view层和controller层的反馈也更加积极。关于SAP UI5和Angular数据绑定的比较,可以参考Jerry这篇文章:https://blogs.sap.com/2016/06…关于SAP UI5和Vue数据双向绑定的实现区别,可以参考Jerry这篇文章:https://blogs.sap.com/2017/06…相对而言微信小程序的数据绑定功能要稍弱一些。首先不提供排序和筛选功能。另外反馈也不够积极:view层改动数据模型需要借助触发事件来调用controller层中的方法进行手动赋值;controller层在更改模型时也必须通过setData方法,才能让改动在view层中生效。(5) 微信小程序的底层是"巨人"微信, 因此可以借助微信方便地调用很多硬件以及软件API,例如:NFC,WIFI,蓝牙,微信运动,生物认证,二维码,登陆以及支付功能等。(6) 纵观两者的控件库,我们可以发现UI5可谓大而全,就连一个表格都要提供responsive table,grid table,smart table等, 目的就是为了支持尺寸各异的不同设备以及各种业务场景。而微信小程序则极其专注在移动端的常用控件,轻量,简易且统一。理念综合以上的比较,我们可以大致发现UI5和微信小程序自面世起便肩负着不同的使命。UI5是SAP为其自研的企业管理软件前端页面所设计的前端框架,以此来实现SAP推荐的Fiori风格的前端应用。它的出现体现了SAP对于确保未来产品拥有统一风格,友好界面和良好用户体验的决心。而微信小程序虽然小,却足以彰显微信扩张的雄心:通过丰富的前后端支持以及简易的上手体验,实现生态圈的急速扩充。而入口和外部访问的限制则是快速扩张的同时,仍然恪守的那份理智。轻量,小巧,快速,简易,移动,一站式。微信想要对你说的是,你的生活,被我承包了。关于SAP UI5和微信小程序,SAP成都研究院的开发人员们做过很多研究,如果您想进行更多阅读,可以参考下面的链接:(1) 我的同事,SAP成都研究院大卫哥Wu David的文章:SAP C4C中国本地化之微信小程序集成(2) 以前Jerry写的SAP UI5框架代码自学教程(3) Jerry在SAP社区上发表过的59篇SAP UI5相关的文章合集(4) Jerry和您聊聊Chrome开发者工具:关于Chrome开发者工具一些搞笑的故事(5) Jerry通过自己调试的方式解决过的UI5的问题合集:https://blogs.sap.com/2016/04…(6) Jerry日常工作中使用Chrome开发者工具积累的一些技巧:https://blogs.sap.com/2016/03…(7) Jerry的碎碎念:SAPUI5, Angular, React和Vue(8) Yang Joey的文章:SAP Cloud for Customer 使用SAP UI5的独特之处(9) 我自己的文章:当我用UI5诊断工具时我用些什么(10) Jerry的文章:在Kubernetes上运行SAP UI5应用(11) Jerry的文章:SAP Fiori + Vue = ?要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 3, 2019 · 1 min · jiezi

SAP技术专家的ABAP调试器培训材料

首先弄清楚ABAP Classic调试器和新调试器的区别:Classic debugger:(1) Static breakpointa. BREAK-POINT : non-user specific b. BREAK user name user specific(2) Dynamic breakpointNew debugger:(1)Static breakpoint(2)Dynamic breakpointa. session breakpointb. external breakpointSession 断点和External断点的区别(1) Session BP is only visible in all external sessions belonging to the same user session, while External BP is visible across all user sessions. Therefore, only External BP is valid for BSP / Webdynpro debugging.(2) When a user logs off, Session BP will be deleted while external BP persists.By setting this flag, if external session A is running, and in external session B ( A and B belongs to the same user session ) you set a session breakpoint in the program source code, the BP will be triggered immediately .ABAP独占断点(Exclusive Breakpoint)和非独占断点的区别下图是非独占断点:下图是独占断点:Exclusive mode means the application to be analyzed exclusively occupies a work process of the application server during debugging. If all exclusive debug work processes are occupied, the Debugger is switched to non-exclusive mode. (rdisp/wpdbug_max_no )Limitation for non-exclusive mode:Due to technical limitations in ABAP debugger implementation, there are following limitations when debugger is run under non-exclusive mode:(1) No possible to debug statement between SELECT and ENDSELECT. In this case, program terminates with this error:(2) No possible for conversion / field exit.(3) No possible for debugging in production system, program terminates with exception DEBUGGING_NOT_POSSIBLE.ABAP调试器里的一些指标该如何阅读?考虑下面这段最简单的ABAP代码:调试器里查看A1这个类型为内表的变量:这里的[2×1(8)]是什么意思?2: table row number1: table column number8: byte length of table rowThe time for which the new Debugger is active is determined by the profile parameter rdisp/max_debug_lazy_time – which is set to 600 seconds in the standard version. After this time space has elapsed, the Debugger process is exited automatically and control is passed back to the application.一些小技巧:how to debug background RFC?解决方案:使用事务码sbgrfcmon小技巧2:如何调试update task小技巧3:如何使用ABAP观察点 Watch point练习:我们进入事务码SE09时,会观察到User字段会自动被填充成当前登录用户。如何通过观察点快速找到是哪一行代码赋的值?When we use SE09, how can we find the logic of the User? When and where is this field filled? What does content come from?Debugging step by step will be very time-consuming.小技巧4:使用ABAP检查组 Check group小技巧5:事务码SRDEBUG小技巧6:调试脚本要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 31, 2019 · 2 min · jiezi

SAP CRM One Order跟踪和日志工具CRMD_TRACE_SET

事务码CRMD_TRACE_SET激活跟踪模式: 在跟踪模式下运行One Order场景。运行完毕后,使用事务码CRMD_TRACE_EVAL:双击参数,就能看到参数明细:点Callstack也能看到调用栈明细:这个工具的实现原理是怎样的?ABAP include CRM_TRACE_PART_ONE做了下面的事情:检查One Order的trace模式是否打开了,如果打开,负责收集调用的时间戳,执行工作进程ID,调用栈上下文:另一个ABAP include CRM_TRACE_PART_TWO负责把调用信息写入INDX表。 在这些ABAP include上使用where used list,可以搞清楚哪些API可以支持跟踪模式。除了用上述事务码打开调试模式以外,也可以设置user parameter “CRM_DEBUG_CODE”来达到同样目的。这个参数的检测包含在include CRM_TRACE_PART_TWO里.ABAP包CRM_TOOLS里还有其他有用的工具:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 31, 2019 · 1 min · jiezi

SAP CRM系统订单模型的设计与实现

SAP成都研究院的一个部门领导让我给他的团队做一个SAP CRM One Order框架的培训,这是我准备的培训内容。在Jerry之前的文章 基于SAP Kyma的订单编排增强介绍,我表达了自己对SAP应用的理解:模型以及基于模型的增删改查。只是同我们大学专业课学习时完成的家庭作业相比,SAP模型的复杂程度增加了好几个数量级。和传统的增删改查相比,以订单编排领域为例,SAP订单模型的"增",还需要考虑实际业务流程中各种类型的前置和后序订单,即SAP使用的术语 文档流(Document Flow)。而"改", 除了订单自身状态的迁移外,还包括订单模型提供的各种可执行逻辑。这些逻辑既包括订单模型本身字段的更改,也可以包括订单与第三方系统的交互。在很多上下文里,我们称这些逻辑为Action。如下图右下角所示:既然订单模型复杂度如此之高,那么引入一种精良的能支持企业级订单编排应用的高质量建模方式,就显得至关重要。随便看些例子,SAP CRM总共支持多少种标准的订单类型?下图中BUS2000开头的就是不同的订单类型,我没有具体数过,但是几十种总是有的。而SAP Cloud for Customer,虽然位于CRM命名空间下面的Business Object的数量比SAP CRM要少一些,但是基本的用于实现销售自动化流程的订单模型仍然一应俱全。我们先来看SAP CRM的订单模型。有没有可能用一套模型来描述SAP CRM支持的几十种订单类型呢?有,那就是SAP CRM One Order模型,其自描述的名称就体现了该模型的特色。Jerry曾经试图搞清楚"One Order"这个称呼,是来自SAP官方,还是仅仅被SAP开发人员内部使用。用搜索引擎根据关键字One Order搜索,得到的结果几乎全是Jerry写的博客,囧。不过进系统根据ONE ORDER为关键字还是能搜索出大把的代码。我的文章 Jerry的WebClient UI 42篇原创文章合集里有这张架构图:其中One Order框架从架构上讲,位于上图红色区域内,包括数据库表,ABAP结构体以及操作它们的API代码。SAP One Order框架有多成功?搜索引擎输入关键字"SAP CRM ONE ORDER", 第一条搜索结果即Jerry写的一篇博客。其中第一段话就给大家做了详细的阐述:尽管它如此成功,但当Jerry刚刚接触One Order的时候,吃惊地发现,竟然没有一个比较直观的图形化界面,能够显示出这个模型的全貌。不过瑕不掩瑜,对于一个诞生于20年前的框架来说,我们不应该用20年后的标准来苛求它。我们想象一下,不同类型的订单,有什么共同点?无非每种订单都有抬头结构,行项目。有的结构,从业务上说可以同时出现在订单的抬头和行项目,比如参与订单的业务伙伴明细(Involved parties), 组织架构(Organization Unit)等等。有的字段只有行项目才能出现,比如卖出的产品信息(Product, Scheduled Line)。SAP One Order建模的原理,类似我们小时候玩的积木。组成One Order模型最小粒度的单元,就是一个个扮演积木作用的结构体,在事务码CRMC_OBJECTS里查看。下图是这些结构体的列表,如果SAP标准的结构体不能满足需要,客户仍然可以自行创建新的结构体。然后我们用搭积木的方式,将业务上具有关联关系的若干结构体组合起来,共同分配给某个订单类型,比如描述服务流程的订单类型BUS2000116,就由下列这些结构体组成:有了模型之后,剩下的就是实现基于这些模型的增删改查操作,即ABAP编程。One Order API的代码实现原理,实际上就是设计模式里的模板(Template)模式和观察-发布者模式的结合体。我们学习模板模式的时候,有一个经典的例子,上帝通过模板模式主宰芸芸众生的生老病死。我们每个人被父母实例化出来之后,只能被动地实现上帝在模板里定义好的四个方法:生,老,病,死,而不能够更改这个模板本身,比如调换这四个方法的顺序。即使是乔布斯,也没有办法给自己添加一个"永生"的方法。听起来很残酷,但这是事实。那么,One Order框架里,作为One Order应用的上帝,定义了哪些模板方法?事务码CRMV_EVENT,指定BUS2000116, 执行:得到下图列表。红色的第一列,就是前文提到的组成One Order模型的积木。蓝色的第二列,是这些积木对发生在自己身上的感兴趣的事件列表。从图中可以看到这些事件名称都是自描述的,比如AFTER_CREATE, BEFORE_CHANGE, BEFORE_DELETE等等。第三列黑色的ABAP函数,就是这些事件的监听函数。这些监听函数的后缀EC代表Event Callback。借助上述框架,One Order应用的开发人员的开发工作就变得无比轻松:1. 通过搭积木的方式,定义出自己应用需要的One Order模型2. 实现模型里需要关注的事件对应的监听函数。至于这些监听函数什么时候被调用到?应用开发人员完全不用操心。由此我们能发现,One Order框架的实现,把编程复杂度从应用开发人员身上转移到了框架实现身上。One Order框架内部的实现比较复杂,一篇文章的篇幅无法讲述清楚。况且通常情况下,One Order框架的使用者只需要了解CRM_ORDER_READ, CRM_ORDER_MAINTAIN等API的用法即可。如果想了解更多细节,可以参考我的SAP社区博客:1. Buffer logic in One Order header extension Readhttps://blogs.sap.com/2017/03…2. Logic of FILL_OW function module in One Orderhttps://blogs.sap.com/2017/03…3. Logic of CHANGE_OW function module in One Orderhttps://blogs.sap.com/2017/03…4. Logic of CREATE_OW function module in One Orderhttps://blogs.sap.com/2017/03…5. Logic of SAVE_EC function module in One Orderhttps://blogs.sap.com/2017/03…6. CHANGED_AT, HEAD_CHANGED_AT and CRM_CHANGED_AT in order header tablehttps://blogs.sap.com/2017/04…One Order的API之一,为消费者提供修改操作的CRM_ORDER_MAINTAIN, 所有SAP标准支持的结构体都作为输入参数之一出现在参数列表里:这种设计方法虽然让参数列表显得有点冗长,但是从另一方面看,也起到了自描述的效果, 确保API的使用者即使不阅读文档,仅凭浏览这些参数本身,就能大概了解该API到底支持One Order哪些数据的修改。这也符合那份著名的来自Google的API设计最佳实践文档里提到的,好的API应该满足的条件之一:易学易用,自描述,不易造成误解。在我的另一篇文章 Hello World, S/4HANA for Customer Management 1.0 我曾经提到,SAP CRM的部分功能迁移到SAP S/4HANA后,部分实现做了一些改造,其中就包括One Order的改造。Jerry是负责One Order改造设计的三位人员之一,详细的改造原理和实现我已经分享到SAP社区了,这里只简述一些核心概念。https://blogs.sap.com/2018/03…https://blogs.sap.com/2018/03…为什么要改造?因为SAP CRM搬到了S/4HANA上,而S/4HANA的一个强大之处,在我同事Zhang Sean的文章 S/4HANA业务角色概览之订单到收款篇 里也提到了,那就是S/4HANA在SAP历史上第一次实现了OLTP和OLAP的完美结合,即一套系统的唯一数据源,可以同时满足Transaction事务型应用和Analytics分析报表型应用的需要。而SAP CRM One Order没有改造之前的模型是无法和S/4HANA的上述特性匹配的。改造之前,每个组成One Order模型最小粒度的结构体,都有自己独立的一张专属数据库表,命名规范一般是CRMD_加上结构体名。这套底层存储模型如果原封不动地搬到S/4HANA里,在运行报表统计等应用时会出现性能问题——为了取出报表结果,后台需要在很多个结构体的存储表中做各种数据库表的内外连接操作。当参与连接操作的数据库表尺寸增长到一定数量级后,整个应用的性能表现不佳。Jerry也参与了性能评测,最后我们决定对One Order的底层数据模型做改造。因为留给我们从调研到改造的原型开发,再到正式开发一共只有八个月的时间,因此我们选择了一种代价最小,对One Order框架改动最小的方式。首先我们抛弃了之前每个结构体拥有一张专属数据库表的做法,在S/4HANA里,每种订单类型只拥有两张表,一张存储抬头级别的数据,另一张存放行项目数据。之前散落在不同结构体表中的字段,如今统一维护在这两张表里。由于所有的字段都平铺在这两张表里,我们内部形象地称其为平坦表(Flattened Table)。存储模型大大简化之后,我们基于这两张表再创建CDS view,让上层的报表应用消费。这样改造后简化的模型,能满足S/4HANA中OLAP应用的需求。针对S/4HANA OLTP应用的改造,用一句话概括,就是我们采用设计模式里的适配器模式(Adapter), 在API与简化后的数据库表之间引入一个微型的中间件,扮演Adapter的角色。当消费者通过One Order API进行读操作时,中间件负责把存储在简化后的数据表中的数据进行还原,再填充到One Order API上层的缓存中。对后者来说,它对底层存储模型发生的变化毫不知情,因为Adapter封装了底层数据读取的逻辑并做了格式转换,所以One Order API上层不需要做任何改动,也完全能够像在SAP CRM里一样正常运行。而当消费者调用One Order API进行写操作时,在存储于各个结构体对应的缓存中的数据持久化到数据库之前,同样是Adapter负责把这些分散在不同缓存结构中的数据做一个合并,合并后的结构体再写入平坦表。讲完了CRM One Order订单模型的设计,我们再来简单看看SAP Cloud for Customer的订单模型设计。虽然SAP Cloud for Customer的后台对客户和Partners不可见,但我们仍然可以从合法渠道获得一些其订单模型的设计信息。https://archive.sap.com/discu…从SAP社区上这位SAP员工的回复,我们得知ESF2和BOPF有很多相似之处,设计理念类似,但ESF2主要用于部署在云端的产品,比如SAP Cloud for Customer上Business Object的开发,而后者主要服务于On Premises解决方案比如S/4HANA。因为Jerry不能够把C4C后台ESF2的界面给大家看,所以我选择了展示S/4HANA的Business Object开发框架BOPF,因为前面说了,二者很多方面都非常相似。同之前介绍的SAP CRM One Order框架一样,通过BOPF实现的订单模型,同样由若干个结构体通过搭积木的方式组成,这些结构体如上图红色高亮区域所示,每个结构体也有自己的专属存储数据库表。而SAP CRM One Order里每个结构体的事件监听函数,采取的是ABAP传统的面向过程的函数实现,而BOPF则采取了实现指定接口的ABAP类,二者原理相同,只是实现细节有差异。SAP C4C的订单模型,虽然和SAP CRM传统的One Order模型一样,每个结构体拥有一张专属的数据库表,但是在运行报表程序时并不会出现性能问题,这是怎么做到的?答案是采用了TREX,一个专为只读报表应用优化过的存储仓库。换句话说,SAP C4C的事务处理和报表处理使用的是两套不同的存储系统,这一点和S/4HANA不同。SAP Cloud for Customer的订单模型,在Cloud Application Studio里对客户和Partners是可见的,大家感兴趣的可以自行去查看。希望这篇文章能让大家对SAP CRM两款产品中的订单模型设计有最基础的认识,感谢阅读。相关阅读SAP的这三款CRM解决方案,您能区分清楚么SAP S4CRM vs C4C, 诸葛亮和周瑜?基于SAP Kyma的订单编排增强介绍要获取更多Jerry的原创文章,请关注公众号"汪子熙":SAP CRM系统订单模型的设计与实现 ...

January 22, 2019 · 1 min · jiezi

SAP Customer Data Cloud(Gigya)的用户搜索实现

我在Gigya前台根据email搜索,输入一个邮箱地址,回车,在Chrome开发者工具里观察到到后台的网络请求:这是一个post请求:__RequestVerificationToken请求体:{“query”:“SELECT * FROM accounts WHERE (profile.email = ‘abc@sap.com’) OR (profile.email CONTAINS ‘abc@sap.com’) OR (loginIDs.emails = ‘abc@sap.com’) OR (loginIDs.emails CONTAINS ‘abc@sap.com’) ORDER BY lastUpdatedTimestamp desc LIMIT 20 START 0”,“format”:“json”,“apiKey”:“3__ZoBjMduuUpCQF86dWF0B-yjUlPDudlQ7FtPlrmxUnKFN”}这次搜索结果的响应:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 22, 2019 · 1 min · jiezi

SAP S/4HANA CDS View的访问控制实现:DCL介绍

来自我的同事Xu MilesAuthorization Objects are business concept, they are distinguished by business scenario.Therefore, there might be a lot of Authorization Objects using the same Authorization Field. Such as VKORG.In Sales Planning, there’re two Authorization Objects related to Sales Area, V_VBAK_VKO and V_VBRK_VKO, they represent transaction scenario Sales Document and Billing Document repectively. If we want to extract the Sales Area master data, technically we could use any Authorization Object with Authorization Field VKORG, VTWEG, SPART.However, considering the authorization of the business user, we need to use Authorization Object V_VBAK_VKO and V_VBRK_VKO separately when end user is planning for income sales or sales volume.To do this, we could use additional CDS view + DCL to realize.Example on ERG/001:CDS: ZMX_SalesArea_DCLDCL: ZMX_SalesArea_DCLThe logic in DCL:@EndUserText.label: ‘Auto assigned mapping role for ZMX_SalesArea_DCL’@MappingRole: truedefine role ZMX_SalesArea_DCL {grant select on ZMX_SalesArea_DCLwhere (SalesPlanPurpose = ‘0’ and (SalesOrganization, DistributionChannel, Division) =aspect pfcg_auth (V_VBAK_VKO,VKORG,VTWEG,SPART,actvt = ‘03’))OR (SalesPlanPurpose = ‘1’ and (SalesOrganization) =aspect pfcg_auth (V_VBRK_VKO,VKORG,actvt = ‘03’));}The logic in the CDS view:define view ZMX_SalesArea_DCLas select fromI_SalesArea{key SalesOrganization,key DistributionChannel,key Division,‘0’ as SalesPlanPurpose}union all select from I_SalesArea{key SalesOrganization,key DistributionChannel,key Division,‘1’ as SalesPlanPurpose};Authorization test on QW9/910User: MILES01Authorization:Test Report:REPORT mx_test_sa_dcl.PARAMETERS:p_purp TYPE C LENGTH 1.DATA:lt_tab TYPE STANDARD TABLE OF i_salesarea_dcl.SELECT * FROM i_salesarea_dcl INTO TABLE @lt_tabWHERE salesplanpurpose = @p_purp.LOOP AT lt_tab ASSIGNING FIELD-SYMBOL(<fs_row>).WRITE:/ <fs_row>-salesorganization, <fs_row>-distributionchannel, <fs_row>-division, <fs_row>-salesplanpurpose.ENDLOOP.WRITE:/ ‘Finished.’.The logic flow is that firstly we use SalesPlanUUID to get SalesPlanPurpose, then with SalesPlanPurpose we could get the Sales Area master data via the corresponding Authorization Objects.SalesPlanPurpose: 0 (Incoming sales)SalesPlanPurpose: 1(Sales Volume)要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 22, 2019 · 2 min · jiezi

SAP S/4HANA里如何创建Customer主数据以及执行后续处理

来自Jerry的同事Zhang Sean.1, Launch tcode: BP and select the Organization2, Maintain the information for Customer role3, Maintain information for name and search4, Maintain the Address5, Maintain the information for Sales and Distribution6, then maintain which Sales Area this customer is assigned to, you could also maintain the information for other Sales Area by the button “Switch Area”. Then after that you shall maintain the information for Order, Shipping, Billing.7, last but the most important, remember to save the BP, then you will get the Customer for the SD business.8, Then you could start business transaction in the defined Sales Area. e.g. create Sales Quotation by Tcode: VA219, The created Customer is entered for the Sold-To Party, and Ship-To Party. And one existing Material is used(Later we will have one exercise to show how to create new Material.)But this time, we see one issue.Pricing error: Mandatory condition TTX1 is missing10, we go to the Item conditions, and click the Analysis to analyze the pricing conditions.11, we got a pricing list, and try to find the TTX1 entry. And the 020 entry is mentioned that Condition Record is missing, we go deeper by clicking the 020 entry under TTX1.12, It seems that there is no condition record maintained for this export taxes.13, Let’s go to the pricing master to maintain export taxes for condition type TTX1.14, enter the information there and save the entry.15, go back to the Quotation Creation Page, where we have the conditions, and click the “Update” to update the conditions automatically. And select the Carry out new pricing. Then the Entry for TTX1 will be proposed in the condition list.16, let’s try again with the Pricing Analysis, you will see the check is also successful.17, let’s go back to the Quotation Header and Save, then there will be one Popup to mention that the document is incomplete. And go to edit and maintain the information accordingly.18, and go back to Quotation Header, it’s mentioned document is complete. So Save it and you did it!19, with that, you managed to create Quotation, and then you could continue the business to create Sales Order, Delivery, Transfer Order, and Billing, Accounting, and Payment.20, Create Sales Order by reference to Quotation: 20004141 (Tcode: VA01)21, Create Delivery by reference to Sales Order: 24615 (Tcode: VL01N)Picking the quantity and Save.22, Post Goods issue for the Delivery (Tcode: VL02N)23, create Billing by reference delivery(Tcode: VF01)24, but in the billing document, it’s mentioned “The journal entry has not yet been created.”. Open the billing document you created with Tcode VF02.And menu: Billing Document, use the option “Release to Accounting"And it’s mentioned “Customer 1000260 is not defined in company code 1010"25, try to define the customer in company code 1010.Open the customer(1000260) in BP, and create new BP role Customer(Fin. Accounting)26, Then go back to the VF02, and use the option “Release to Accounting”, this time, the release will be successful. The accounting documents are generated. You could check this with the document flow.27, in the document flow, but the last account document is still not cleared, where payment is needed from customer, but before that, you need to know how much the customer will pay.You could open the billing document by VF03, and goto28, then you got to know 1498 is the amount. Go to the accounting receivable.(Tcode: F-28)29, Open the Document flow, then all the accounting documents are clear!, Well done, you made it.要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

January 22, 2019 · 3 min · jiezi

SAP S/4HANA extensibility扩展原理介绍

SAP产品总的extensibility扩展原理介绍:看Jerry这篇文章。SAP Cloud for Customer Extensibility的设计与实现我的同事Boris写的。而本文是S/4HANA extensibility扩展性专题:Enhancement ConceptSCFD_REGISTRY - Extensibility RegistryBusiness ContextExtensible CDS ViewExtension field is available, extend view generate, on registered CDS view.Extensible OData ModelUse report CFD_CREATE_FLX_CLASS to generate classes …MPC_FLX and …DPC_FLXData Transfer and Business Scenario要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 22, 2019 · 1 min · jiezi

SAP Cloud for Customer Account和individual customer的区别

在SAP Cloud for Customer的Customers工作中心里,有三个视图:Accounts,Contacts和Individual Customers。这三种主数据的区别是什么?我们可以从它们后台的BO模型开始分析。Account视图的UI模型:/BYD_COD/SalesOnDemand/Account/UI/COD_Account_TI.TI.uicomponent后台BO为Customers:再看Contact视图:Contact:后台BO:BusinessPartner再看Individual Customer:6$/BYD_COD/ServiceOnDemand/PrivateAccount/COD_SEOD_IND_ACCOUNT_TI.TI.uicomponent模型依然是Customers。那么Account和Individual Customer都用了Customers作为BO,有什么区别?答案是,Account数据,后台的BO数据CategoryCode为2:而individual Customer的CategoryCode为1:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践

培训者:SAP成都研究院开发人员Jerry Wang1. Understanding Memory Objects in ABAPNote1: DATA itab WITH HEADER LINE for processing individual table rows have short forms that implicitly use the header line as work area. These short forms are allowed only outside of ABAP Objects./SF0A0001/ANONYMOUS4951422. Use Reference to Access Memory ObjectABAP里引用的用法3. ABAP和很多其他语言一样,支持写时拷贝:As internal tables and strings can become very large, the copy operation may be quite time-consuming. On the other hand, the copy operation is only necessary if a modification is made via one of the references, which is NOT always the case.For this reason, ABAP runtime delays the copy operation until a modification is actually made. These object types (internal tables and strings) keep track of the number of references that point to them, which is referred to as “reference counting.”4. 写时拷贝的工作原理5. ABAP的内存管理之内存清理内存释放关键字CLEAR,REFRESH和FREE的区别:6. ABAP引用类型的内存分配7. ABAP字符串(String)类型的内存分配8. ABAP内存垃圾回收器的工作原理9. ABAP内存垃圾回收的实现算法10. ABAP垃圾回收机制的触发时机11. ABAP垃圾回收的手动触发,请谨慎使用12. 更多关于引用类型的变量在ABAP垃圾回收算法中的影响13. ABAP bound memory的含义the sum of the size of the memory object and the bound memory of all DIRECT children that are table bodies or strings with a reference count of one.Upon deleting the memory object, the bound memory is the minimum amount of memory that is released, and the referenced memory is the maximum amount that can be released. Therefore, the amount of memory that is actually released is somewhere between these two values.14. ABAP内存预分配算法(preallocation mechanism)介绍15. ABAP已分配内存和已使用内存的区别For internal tables and strings, ABAP runtime environment uses a preallocation mechanism that automatically reserves some EXTRA storage when the memory object is created to allow for potential growth.It avoids many allocation and deallocation operations. Otherwise, ABAP runtime environment would have to allocate new storage every time the memory object grows.Due to this preallocation mechanism, both internal tables and strings also have “allocated memory” and “used memory” values as memory sizes.Allocated memory is the amount of memory that is set aside for the memory object. Used memory is the current size of the memory object used by the application.For class objects and anonymous data objects, used memory and allocated memory are the same. Because their size is fixed, they don’t require additional space to accommodate growth.16. ABAP程序内存消耗的尺寸计算介绍17. 什么是ABAP内存分配中的SCC - strongly connected component - 强连通组件18. 有用的ABAP内存分析和调优工具,事务码S_MEMORY_INSPECTOR19. 具体例子,您知道下面这段代码,新生成的引用类型的变量,内存是从哪里分配的?堆?不完全对。Logging on to an application server opens a user session. A user session is assigned its own memory area of the SAP memory, in which SPA/GPA parameters can be stored.For every user session , a main session ( external session ) can be opened. Each main session is assigned its own memory area of ABAP memory ( EXPORT — IMPORT ) rdisp/max_alt_modesEach call of an ABAP program creates a new internal session, in which the called program is loaded.20. 什么是ABAP程序的PXA - Program Execution Area21. ABAP程序的用户上下文 - User Context22. 什么是ABAP的工作进程23. ABAP工作进程的内存虚拟地址空间和物理地址空间的映射Roll Area:Memory area with a set (configurable) size that belongs to a work process.For technical reasons, the roll area is always the first memory available to use for a work process. Only afterwards can extended memory be requested.When the context of a work process changes, the data is copied from the roll area to a common resource known as the roll file. To prevent repeated copying, another roll buffer is located in between, which is part of the shared memoryPaging area:Allocation of memory for the current internal session by transferring pages out of memory, similarly to operating system paging. SAP’s memory management concept currently limits SAP Paging to cases where the ABAP commands EXTRACT and EXPORT… TO MEMORY… are used.Private memory:If the extended memory is fully occupied, or the limit for the work process has been exceeded, private memory is assigned to the work process. This is known as private memory because it is specific to the process, and the user context can no longer be processed by a different work process (PRIV mode).ABAP扩展内存 - extended memoryUser context is stored in the extended memory (EM) to enable fast context change . Depending on the operating system, how SAP implements EM addressing/mapping is different.When the context is changed, the user context is not copied as with the roll area. Instead it is allocated to alternating work processes by mapping operations which results in a faster context change because less data is copied and mapping an extended area is not work-intensive. The result is low CPU usage and shorter access times.SAP dispatcher is responsible for the following principle tasks:1. Initialization, reading profile parameters, starting work processes and logging on to the message server2. Evenly distributing the transaction load across work processes3. Connecting to the GUI layer4. Organizing communication processes这道题的答案:The roll area consists of two segments. The first segment, which can be set with the parameter ztta/roll_first, is assigned to the work process first as memory. If this is used up, the work process has more memory assigned to it. The amount of memory is determined by the difference between the ztta/roll_area and ztta/roll_first parameters.正确答案,不能一概而论,有三种情况。情况1:Roll area: if ( roll_current_area + request size <= roll_area )情况2:Extended memory: if ( roll_current_area + request size > roll_area ) AND ( extend memory is not full )情况3:Private memory: if ( roll_current_area + request size > roll_area ) AND ( extend memory is full )要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 4 min · jiezi

150行JavaScript代码实现增强现实

增强现实技术(Augmented Reality,简称 AR),是一种实时地计算摄影机影像的位置及角度并加上相应图像、视频、3D模型的技术,这种技术的目标是在屏幕上把虚拟世界套在现实世界并进行互动。这种技术1990年提出。随着随身电子产品CPU运算能力的提升,预期增强现实的用途将会越来越广。本文介绍使用JavaScript开源框架AR.js实现的增强现实的Hello World例子。先看效果:首先在手机浏览器里打开我部署在github page上的这个demo应用:https://i042416.github.io/FioriODataTestTool2014/WebContent/098_ar.html我用的是Android手机安装的Chrome浏览器。打开网页,会提示你是否允许这个网页应用访问您的手机摄像头。点击允许:用手机上的摄像头扫描这张图片:神奇的事情就发生了。您会看到,通过手机摄像头望过去,手机屏幕里会出现一个新的不断滚动的3D物体,如下图所示。下面具体介绍这个最简单的例子是怎么开发出来的。所有的源代码在我的github上:https://github.com/i042416/FioriODataTestTool2014/tree/master/WebContent/ar新建一个html文件,把下列150行代码粘贴进去,然后在服务器上运行,使用之前描述的步骤即可进行AR测试:<!DOCTYPE html><meta name=“viewport” content=“width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0”><script src=‘ar/lib/three.min.js’></script><script src=“ar/lib/stats.min.js”></script><script src=“ar/lib/ar.js”></script><script>debugger; THREEx.ArToolkitContext.baseURL = ‘’;</script><body style=‘margin : 0px; overflow: hidden; font-family: Monospace;’><div style=‘position: absolute; top: 10px; width:100%; text-align: center; z-index: 1;’><script> var renderer = new THREE.WebGLRenderer({ // antialias : true, alpha: true }); renderer.setClearColor(new THREE.Color(’lightgrey’), 0) // renderer.setPixelRatio( 1/2 ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.domElement.style.position = ‘absolute’ renderer.domElement.style.top = ‘0px’ renderer.domElement.style.left = ‘0px’ document.body.appendChild( renderer.domElement ); // array of functions for the rendering loop var onRenderFcts= []; // init scene and camera var scene = new THREE.Scene(); var camera = new THREE.Camera(); scene.add(camera); var arToolkitSource = new THREEx.ArToolkitSource({ // to read from the webcam sourceType : ‘webcam’, // to read from an image // sourceType : ‘image’, // sourceUrl : THREEx.ArToolkitContext.baseURL + ‘../data/images/img.jpg’, // to read from a video // sourceType : ‘video’, // sourceUrl : THREEx.ArToolkitContext.baseURL + ‘../data/videos/headtracking.mp4’, }) arToolkitSource.init(function onReady(){ onResize() }) window.addEventListener(‘resize’, function(){ onResize() }) function onResize(){ arToolkitSource.onResize() arToolkitSource.copySizeTo(renderer.domElement) if( arToolkitContext.arController !== null ){ arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) } } var arToolkitContext = new THREEx.ArToolkitContext({ // cameraParametersUrl: THREEx.ArToolkitContext.baseURL + ‘../data/data/camera_para.dat’, cameraParametersUrl: ‘ar/data/data/camera_para.dat’, detectionMode: ‘mono’, maxDetectionRate: 30, canvasWidth: 803, canvasHeight: 603, }) arToolkitContext.init(function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); }) onRenderFcts.push(function(){ if( arToolkitSource.ready === false ) return; arToolkitContext.update( arToolkitSource.domElement ) }) var markerRoot = new THREE.Group scene.add(markerRoot) var artoolkitMarker = new THREEx.ArMarkerControls(arToolkitContext, markerRoot, { type : ‘pattern’, patternUrl : THREEx.ArToolkitContext.baseURL + ‘ar/data/data/patt.hiro’ }) // build a smoothedControls var smoothedRoot = new THREE.Group() scene.add(smoothedRoot) var smoothedControls = new THREEx.ArSmoothedControls(smoothedRoot, { lerpPosition: 0.4, lerpQuaternion: 0.3, lerpScale: 1, }) onRenderFcts.push(function(delta){ smoothedControls.update(markerRoot) }) var arWorldRoot = smoothedRoot // add a torus knot var geometry = new THREE.CubeGeometry(1,1,1); var material = new THREE.MeshNormalMaterial({ transparent : true, opacity: 0.5, side: THREE.DoubleSide }); var mesh = new THREE.Mesh( geometry, material ); mesh.position.y = geometry.parameters.height/2 arWorldRoot.add( mesh ); var geometry = new THREE.TorusKnotGeometry(0.3,0.1,64,16); var material = new THREE.MeshNormalMaterial(); var mesh = new THREE.Mesh( geometry, material ); mesh.position.y = 0.5 arWorldRoot.add( mesh ); onRenderFcts.push(function(){ mesh.rotation.x += 0.1 }) var stats = new Stats(); document.body.appendChild( stats.dom ); // render the scene onRenderFcts.push(function(){ renderer.render( scene, camera ); stats.update(); }) // run the rendering loop var lastTimeMsec= null requestAnimationFrame(function animate(nowMsec){ // keep looping requestAnimationFrame( animate ); // measure time lastTimeMsec = lastTimeMsec || nowMsec-1000/60 var deltaMsec = Math.min(200, nowMsec - lastTimeMsec) lastTimeMsec = nowMsec // call each update function onRenderFcts.forEach(function(onRenderFct){ onRenderFct(deltaMsec/1000, nowMsec/1000) }) })</script></body>当然,这个效果来自大神jeromeetienne开源的AR.js:https://github.com/jeromeetienne/AR.js/当然大神自己也很谦虚地提到,他这个开源的增强现实框架也是建立在巨人的肩膀上开发的:比如其中3D效果的绘制,使用到了另一个开源框架three.js:要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 2 min · jiezi

ABAP文档生成工具

本文介绍的工具原理和JavaDoc类似,位于software component BBPCRM1. 在ABAP类里新建一个名为CLASS_DOCU的私有方法。然后把所有的注释写在这个方法源代码的前面。2. 在每个方法前面,采用和JavaDoc语法一样的方式对ABAP方法书写注释,比如@param修饰输入参数,@return修饰返回参数等。3. 所有方法的文档书写完毕之后,使用事务码CLASS_DOCUGEN生成文档。4. 接下来在事务码SE24,SE80里就可以在class builder里查看这些生成的文档了。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

S/4HANA业务角色概览之订单到收款篇

大家好我叫Sean Zhang,中文名张正永。目前在S/4HANA产品研发部门任职产品经理,而这一阶段要从2017年算起,而在那之前接触更多还是技术类的,比如做过iOS、HANA、ABAP、UI5等等开发。然后在团队中负责设计和架构之余,也尝试做过一些SAP内部培训课程的讲师,比如在HANA、Fiori、Architecture Modeling等方面。我所在的团队,S/4HANA Sales(SD)成都团队,主要负责S/4HANA里销售模块相关的标准应用研发,或者笼统的理解为SD(Sales and Distribution 销售与分销)模块相关的,所以后续我就用SD简称。如果要追溯的话,我们团队应该是从2012年开始参与SD的产品开发,然后在2014年加入S/4HANA的研发。从最开始主要耕耘在底层的数据模型,到现在我们参与或主导了SD的分析、定价、合同、开票等等领域,当然SD产品的研发部门除了在成都还在欧美多地有研发团队。S/4HANA SD成都团队不仅在多个SD的核心领域有贡献,同时在一些重要前沿也属于先行者,比如在探索机器学习方面,团队最近尝试的一嵌入式机器学习应用也有幸被授予SAP中国研究院的2018年度的最佳产品之一。如果大家对于机器学习如何在S/4HANA中落地感兴趣,下次我的团队成员也可以跟大家一起分享和讨论。今天跟大家分享在订单到收款(Order-to-Cash,有时也简写为O2C)流程中的业务角色,通过熟悉这些主要业务角色,不仅能了解O2C的业务和解决方案,也能了解业务角色在整个S/4HANA里的运转模式继而推而广之。如果大家有关于S/4HANA产品的问题,特别是SD模块的,可以留言讨论。背景过去的企业业务系统,由于技术限制,需要在多方做出不同程度的平衡,比如数据处理的深度,广度,响应的高速性,实时性和简单性等等。当需要专注在数据的广度和深度分析时,会更像是一个OLAP(在线分析处理)系统,而需要实时快捷处理事务操作时更偏向于OLTP(在线事务处理)系统。在S/4HANA里,第一次实现了OLTP和OLAP的完美结合,大部分的业务可以在一套系统的一个数据源上完成。以往一个用户需要在多套系统间来回切换,然后再汇总数据,特别是在月末或季度末,通过漫长等待才能得到最终数据报表的岁月已经成为历史。在S/4HANA里,对于业务人员,一切变得简单和实时,这体现了2014年时SAP提出的一种系统设计思想设想——至简(Simplicity)。事务和分析操作融为一体,这也是为什么在S/4HANA里,我们不仅有事务处理,还有嵌入式分析(Embedded Analytics)。至简不仅仅意味着系统架构的简化,同时也包括业务流程的简化。在过去,每个业务人员需要面对繁杂的基于功能的应用界面,如下左图示例:而在S/4HANA里,所有的应用和解决方案都是基于角色提供(Role Based),换言之,每个业务人员只需要关注跟自己相关的信息,而这主要是通过IAM来实现。IAM的全称叫身份和访问管理(Identity and Access Management),负责确保业务用户访问应用的安全性。业务用户通过业务角色获得 Fiori 应用的访问权限。业务角色可包含一个或多个业务目录,从而包含多个应用。更多细节可以参考最新的SAP帮助文档。为了帮助企业更便捷的使用这一套基于角色的方案,S/4HANA在不同的模块为不同的经典业务角色预定义了各种角色模板,比如在财务领域有应付账款会计、应收账款经理、总账会计等;在销售领域有内部销售代表、销售经理等等。企业的关键用户基于角色模板创建角色,并根据实际业务进行调整,最后赋予每个具体的用户。SAP发布的标准业务角色模板有40个以上,而对于不同行业和国家提供超过200个模板,具体信息可以参照IAM的应用“业务角色模板”。业务角色是为业务服务的,不同的业务需要有不同的应用,继而其需要的业务角色模板也会不同。每个企业的业务在专属领域里会直接或间接的需要有不同的业务流程,比如:从商机到收款(Lead to Cash)从寻源到付款(Source to Pay)从差旅到报销(Travel to Reimburse)从市场到商机(Market to Lead)从设计到运营(Design to Operate)据不完全统计,大部分企业里有超过十个端对端的业务流程。而今天我们的讨论源于从商机到收款这个流程,其通过C/4HANA和S/4HANA的结合可以完整落地。在S/4HANA 销售模块(Sales-SD)中主要是解决该流程中的订单到收款(Order to Cash)这一部分。当然直接面向客户(C-Customer)的商机到订单(Lead to Order)主要是在C/4HANA中完成。接下来我们就一起详细探讨一下从订单到收款流程。从订单到收款在从订单到收款的整个过程中,按照维基百科的解释主要有九大流程:https://zh.wikipedia.org/wiki…S/4HANA,作为企业的数字核心(Digital Core),从订单的录入和履行到开票和付款都能完整体现在系统层面。其中一些典型的流程可以用下图表示:为了保驾护航这些流程,S/4HANA的销售领域已经提供的标准角色模板有:(1) 定价专家(SAP_BR_PRICING_SPECIALIST)(2) 内部销售代表 (SAP_BR_INTERNAL_SALES_REP)(3) 退货与退款职员(SAP_BR_RETURNS_REFUND_CLERK)(4) 开票员工(SAP_BR_BILLING_CLERK)(5) 销售经理 (SAP_BR_SALES_MANAGER)(6) 销售流程经理 (SAP_BR_SALES_PROCESS_MANAGER)当然为了完整实现订单到收款,还会有其他角色,比如装运专家(SAP_BR_SHIPPING_SPECIALIST)和应收账款会计(SAP_BR_AR_ACCOUNTANT)等等,如果大家有兴趣今后我们可以单独分享。接下来我们对订单到收款流程中这几个角色逐一介绍,希望借此能帮助大家理解各种业务角色在标准的企业管理中的常见任务与活动。因为我所在的团队正好负责其中销售经理和销售流程经理相关的应用研发,如果有任何问题也欢迎讨论。1. 定价专家此角色主要负责管理销售中的定价,使价格保持为最新状态并使其及时可用。定价专家定义销售中的定价条件记录。基于这些数据和配置专家进行的定价配置,系统计算销售凭证和开票凭证中的价格和成本。其中包括维护特定赠品的特定条件记录(排除奖励数量或包含奖励数量)。在订单到收款的流程中,定价专家会在业务开始之前就会加入,属于偏主数据管理的范畴。因为大多数的事务操作都离不开价格的设置。当然在实际业务中,由于销售策略和市场的变化,定价也会有调整。此角色能开展以下任务:创建、更改、显示和删除用于价格、折扣和附加费的条件记录执行价格、折扣和附加费的批量变更创建、更改、显示赠品的条件记录2. 内部销售代表此角色主要负责管理各种销售凭证和主数据记录。截图中展示的是销售订单相关的应用,其实从下面长长的单子就能发现在内部销售代表这个角色里有非常多的应用,不管是对各种不同的销售凭证的管理,还是对销售相关的主数据维护,甚至监控凭证履行等等。一方面说明内部销售代表在企业的日常运营的重要性,另一方面从标准产品的角度提供了灵活性,每个企业可以基于标准的角色,根据不同类别的细分用户类去建立特定的业务角色,通过增加或删除一些业务目录从而达到对具体销售人员的权限管理。在订单到收款的流程中,内部销售代表会负责大部分报价和订单管理的活动,从订单的录入到订单的履行,同时跟其他业务角色也有合作,比如装运专家,仓库人员。此角色能开展以下任务:创建、更改和显示销售凭证,如以下项:销售询价、销售报价、销售合同、销售订单或借项和贷项凭证请求管理不同销售凭证清单,例如,重复或不完整的销售凭证跨整个从订单到收款场景流程组件跟踪销售订单状态查看关于客户的信息显示主数据记录、如物料或业务伙伴创建销售主数据记录,例如,客户物料在我的销售概览应用中显示有关各种销售活动的信息在销售订单履行流程中监控、解决和协调重要的未处理问题配置并管理产品分配作为检查销售和库存运输订单中物料可用性的方法监控特定时间期间内产品分配对象、分配期间、特征值组合和订单项目的产品分配情况附上一些相关的应用截图。3. 退货与退款职员此角色主要负责客户退货管理以及触发退款。在订单到收款的流程中,如果涉及到客户因为商品质量等原因需要退货,就需要由企业的退货职员管理。此角色能开展以下任务:从开票凭证或销售订单中创建客户退货编辑客户退货确定客户退货退款查看客户退货详细信息处理无费用销售订单4. 开票员工此角色主要负责监控和管理所有开票流程。开票管理是在订单到收款流程中,从销售领域到财务领域的重要环节。开票员工需要基于前导凭证去管理这个环节,甚至负责管理销售佣金等事宜。此角色能开展以下任务:基于先前凭证(例如,交货、开票凭证请求和借贷凭证请求)创建、管理、更改和输出开票凭证(例如,发票、贷项凭证和借项凭证)并将其过账到财务会计基于先前凭证创建、管理、更改和输出临时开票凭证创建、管理、更改和输出由开票凭证组成的发票清单创建和管理可从内部和外部源中持久保存可开票数据的开票凭证请求以条件合同的形式管理返利协议和销售佣金生成和管理条件合同的结算凭证以结算返利协议并在客户财务会计中创建付款创建部分、增量和最终结算以及增量应计结算5. 销售经理此角色主要负责监控和优化销售流程和销售计划,并分析销售特定的关建性能指标 (KPI),例如,销售量和利润率。前序的四个角色可以把主要的事务流程完成,但是对于一个企业的管理而言,分析和监控业务的运营状况至关重要。所以销售经理的活动会从订到到付款的整个过程贯穿始终。此角色能开展以下任务:监控和优化销售流程和销售计划分析销售特定的 KPI,例如,报价转换率、销售合同转换率、新接销售订单、延期交货订单、交货绩效、销售量、利润率和贷项凭证获取与您最相关的销售特定 KPI 的图形概览,例如,收到的销售订单、客户退货、不完整的销售凭证、延期交货订单、利润率、已冻结和逾期销售订单通过实时计划和分析预测销售并设置目标关于销售计划的解决方案,可以参照我的这篇博客:S/4HANA之管理销售计划入门https://blogs.sap.com/2018/03…为了帮助销售经理更智能化的监控和优化销售流程,在S/4HANA里,我们提供了嵌入式预测分析解决方案。https://blogs.sap.com/2018/06…附上一些相关的应用截图。6. 销售流程经理此角色主要负责从订单到收款流程,需要了解企业中的所有销售订单流程的绩效和一致性。流程经理借助S/4HANA的流程业绩监控解决方案开展活动,监控流程中某些步骤的持续时间,以及执行流程期间触发的重要事件出现次数的关键指标。通过这些关键指标的帮助,流程经理可以轻松确定销售流程的运行状态是否良好,并能够快速找出有待改善的区域。此角色可开展以下活动:跟踪交货冻结或开票冻结检测对销售订单的关键字段进行的更改监控提前期(例如从订单到交货或从发货到开票的提前期)关于订单到收款流程绩效监控,后续我单独再分享。如果想提前了解也可以参考这篇SAP社区的博客:Order-to-Cash Performance Monitoring in S/4HANAhttps://blogs.sap.com/2015/09…总结通过对S/4HANA的销售模块中主要业务角色的介绍,大家应该对从订单到收款流程中的角色活动有一个基本的了解,同时对于如何在S/4HANA里去实现OLAP和OLTP的结合有一个直观的感觉。更多详尽的内容请参照SAP官方帮助文档,如果有任何问题,欢迎讨论,谢谢大家。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

SAP C/4HANA Sales Cloud使用OData服务和第三方系统集成的一个具体例子

出于工作需要,Jerry写了这篇文章,给某些Partner做参考。以前Jerry曾经介绍过SAP C/4HANA的五朵云到底包含哪些具体产品,其实在SAP官网上有更权威的中文解释:https://www.sap.com/china/pro…其中明确提到销售云包含SAP Cloud for Customer(C4C),SAP Revenue Cloud和Callidus Cloud。有Partner询问有没有更详细的步骤介绍,关于如何在第三方系统里调用SAP C4C暴露出的Restful API进行集成。本文就给出一个具体的例子,将SAP C4C销售订单的创建功能通过自定义的OData服务暴露出来,然后Partner可以根据项目需要选择合适的编程语言(本文选择JavaScript)来消费。Jerry以前发布过一个视频,演示了如何在SAP C4C里手动创建一个销售订单,步骤可以说简单易懂。https://v.qq.com/x/page/d0809…现在我们通过OData的方式将销售订单的创建功能暴露出来,就能在第三方系统或者应用里完成C4C的订单创建。大家如果对SAP OData还不太了解,可以先读一读我这篇文章开头的部分:SAP OData编程指南下面是详细步骤。登录C4C系统,访问工作中心Administrator,工作中心视图OData Service Explorer,这里可以在SAP发布的标准OData服务和客户自定义的OData服务之间切换。因为客户自定义OData服务能够允许客户自行决定从哪一个Business Object的哪一些节点,选择哪一些字段来生成OData模型,通过这种灵活的方式可以避免Business Object上客户业务场景里不需要的字段出现在OData模型中。点击New按钮新建一个OData服务:给Work Center View字段指定一个用来做权限控制的视图,只有分配了这个视图的用户才有权限访问这个OData服务。点击Select Business Object从弹出对话框中选择基于哪一个Business Object创建OData模型。下图就是一个已经创建好并处于Active状态的OData服务。左边显示的是CustomerQuote这个BO的Root节点的所有字段,每个字段都有一个可以勾选或取消的Select属性,勾选则该BO字段会出现在右侧的OData模型里。除了Root节点之外,BO的其他子节点上的字段当然也是可以出现在OData模型里的,比如我上图右边OData模型的子节点CustomerQuoteItem, CustomerQuoteParty和CustomerQuoteText等,就是分别从左边BO的同名节点选中后自动带到右边的OData模型中去的。理论上,完成基于BO模型进行OData模型的创建并激活后,这个OData服务就可以使用了,这体现了SAP C4C OData服务自定义框架的强大之处。然而我也收到了一些朋友从后台给我提的一些问题,罗列如下。问题1: 仍然以本文销售订单创建这一场景为例,假设我希望我创建的OData服务能够允许消费者调用时指定External Reference的值,但是我找遍整个BO列表,也没发现销售订单的BO上有叫这个名称的字段啊?Jerry答:External Reference是UI文本,不是BO字段的技术名称。给C4C系统在浏览器里的url添加参数debugMode=true, 然后刷新页面,按住Ctrl键再单击External Reference字段,就能看到这个UI字段绑定到UI模型上哪一个字段了。在这个UI模型字段上再点击Show Model,就能看到这个UI模型字段绑定到的BO字段名称为BuyerID。所以我们在OData开发工具里,只需把BO字段BuyerID选中,移动到右边的OData模型里即可。问题2:我想让我的OData服务支持行项目数据的创建,比如指定产品ID,描述和购买数量等等。我怎么知道哪些BO节点上的字段需要添加到OData模型中去?Jerry答:现在我们换一种方法,打开Cloud Application Studio的UI Designer,定位到销售订单创建页面的UI模型COD_SALESORDER_QC, 找到Product ID字段,在它的Properties面板里即可看到这个Product ID字段绑定的BO字段的名称和完整路径:Root-.ItemProposal-~ProductUUID-~content因此我们需要将BO对应路径下面的ProductUUID字段添加到OData模型中去。这里能观察到ProductID的Create和Update是没有勾选上的,而ProductUUID则支持Create和Update,这个行为和C4C销售订单行项目创建的标准实现有关——消费者需要提供待创建行项目包含的产品UUID,然后C4C会根据UUID到系统中查询出对应的产品,显示其ID到UI上。如果消费者在调用OData服务时,没有指定ProductUUID,则行项目创建逻辑不会执行。OData模型创建好之后,在用编程语言消费之前,我们可以先用工具Postman(或者C4C自带的测试工具)进行测试。因为SAP C4C后台对Cross-site request forgery(跨站请求伪造)这种攻击采取的防御实现和SAP CRM,SAP S/4HANA一样,采取的是CSRF token验证机制,因此我们在调用OData服务进行销售订单创建时,需要将一个合法的CSRF token一并传递给C4C系统。如何得到一个合法的CSRF token呢?在Postman里构造一个HTTP GET请求,头部字段名为x-csrf-token, 值为fetch:发送这个HTTP GET请求,服务器端会生成一个CSRF token,通过HTTP响应结构头部字段x-csrf-token返回给消费者:sNwnYC9cV4xeGSYZmJ8Dtw==下面我们再在Postman里新建一个HTTP Post请求,将之前通过HTTP GET拿到的CSRF token,以HTTP Post请求头部字段的方式发送给C4C系统。关键在于HTTP Post请求的请求体。下图高亮部分是我在HTTP Post请求里指定的创建销售订单的输入数据:在Postman里发送这个Post请求,几秒钟后得到C4C的响应,订单创建成功,ID为9000000451:为了方便大家对比,下面是我用Postman消费我创建的OData服务生成的销售订单在系统里的显示。字段1~6对应的Postman输入字段可以在前文找到。蓝色区域高亮显示的字段,我在Postman里构造的输入里并没有维护,而是通过SAP C4C系统的各种determination配置,自动决定出来的。最典型的有SAP老司机们天天打交道的Partner determination,Organization determination,Pricing determination等。Postman里测试通过后,就可以写代码消费了。如果想直接复制粘贴我下面列出的代码,可以从我的github上获得:https://github.com/i042416/Kn…注意本代码只用于演示目的,缺少健壮的出错处理,不能直接用于生产环境中。下面的代码使用nodejs提供的request模块向C4C请求CSRF token。注意第3行的url和第11行的Authorization头部的值,我都是用的虚假值,请大家替换成自己实际使用的C4C url和认证信息。Token拿到之后,将其放入第41行构造的HTTP Post请求的头部结构中,作为字段x-csrf-token的值。第47行发送该POST请求,C4C响应的数据存放于JavaScript变量data中。最后我通过简单的console.log打印出创建成功的销售订单ID:在命令行里用node执行这个js文件,会打印出从C4C获取到的CSRF token,以及成功创建的订单ID。我们再回顾一下用SAP C/4HANA Sales Cloud中的C4C OData同外部系统做集成的三个主要步骤:1. 在C4C的OData模型编辑页面里,根据业务需要,从对应的BO节点里选择合适的字段,添加到OData模型中。2. 用Postman或者C4C自带的OData测试工具对OData模型进行测试,确保其正常工作。3. 根据项目需要选择合适的编程语言消费OData服务。如果对于SAP C4C OData有更多的问题需要讨论,欢迎留言。感谢阅读。Jerry关于OData的更多文章1. SAP OData编程指南2. OData服务同步模式和异步模式的讨论https://blogs.sap.com/2015/06…3. OData服务的性能分析https://blogs.sap.com/2015/07…https://blogs.sap.com/2016/01...4. 基于SAP CDS view生成OData服务https://blogs.sap.com/2016/03…5. OData的offline支持5.1 https://blogs.sap.com/2016/08…5.2 https://blogs.sap.com/2016/08…5.3 https://blogs.sap.com/2016/08…6. 使用ABAP消费SAP C4C标准OData服务https://blogs.sap.com/2017/08…7. SAP CRM,C4C和S/4HANA里OData服务实现的横向比较https://blogs.sap.com/2017/08…8. 使用Java和jMeter对需要支持CSRF验证的OData服务进行高并发性能测试https://blogs.sap.com/2017/08…9. 使用C4C OData + ABSL消费自定义BO的逻辑https://blogs.sap.com/2017/12…要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 1 min · jiezi

SAP C/4HANA与人工智能和增强现实(AR)技术结合的又一个创新案例

今天这篇迟到的文章,来自我的同事Aviva。去年SAP C/4HANA发布之后,SAP的从业者们可能或多或少都读过一些来自SAP官方渠道,比如微信公众号"SAP天天事"发布的一些文章,提到了"企业数字化转型", “智慧企业"等概念。那么这些概念如何落地呢?请看本文介绍的SAP成都研究院数字创新空间做出的一个尝试。Jerry在去年Aviva的一篇文章 Hyperledger Fabric on SAP Cloud Platform里就曾经介绍过她,不过Jerry也是最近才得知她"英文"名字的由来:“Aviva"这个单词,在希伯来语里的意思是"美好的春天”, 而这篇文章的作者Aviva,中文名字里正好有一个春字。为什么说是迟到的文章呢?因为这个创新案例早在去年上半年就结束了,然而作为同事们评价的"美腻与智慧的化身”,“云时代女王”,“大家前沿技术的引路人”, Aviva工作上总是有很多事情要忙,因此直到项目做完的半年后,才能空出档期完成这篇文章。此外,Aviva的正文里所有关于案例的截图都是从SAP成都研究院数字创新空间另一位女同事,Zhang Jane(张琦)制作的演示视频中截取的,这里表示感谢。Jane制作的关于这个创新案例的展示视频:<iframe frameborder=“0” width=“677” height=“380.8125” allow=“autoplay; fullscreen” allowfullscreen=“true” src=“https://v.qq.com/txp/iframe/p...;amp;vid=m0823f5fo83&amp;autoplay=false&amp;full=true&amp;show1080p=false&amp;isDebugIframe=false" style=“margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"></iframe>Jane是一位美貌与才华并重的女同事,我在文章 SAP成都研究院数字创新空间沟通S/4HANA和C/4HANA的智能服务演示视频和Coresystems分享预告 里曾经贴过张琦的绘画和书法作品。这里再贴两张Jane元旦画的画,算是。。。算是给大家拜个早年:下面是Aviva的正文。*大家好,我是SAP成都研究院的开发人员Aviva。今天我想给大家分享一个我去年参与开发的项目,在SAP C/4HANA上结合近些年比较热门的人工智能和增强现实技术打造的一个创新案例。这个案例只是一个原型开发,并不是C/4HANA已经发布的标准功能。人工智能大家或多或少都有所了解,而增强现实技术(Augmented Reality,简称 AR), 按照维基百科的介绍,是一种实时地计算摄影机影像的位置及角度,并伴之与相应图像、视频和3D模型参与的技术,其目标是在屏幕上把虚拟世界的物体渲染在现实世界并允许使用者进行互动。听起来有点抽象和高深?我们马上进入案例介绍,通过实际的例子大家就能理解这个技术的用途了。而增强现实技术在移动设备上的实现,我们作为应用开发人员,可以简单的使用网上一些流行的AR开源框架进行应用开发。至于这些开源框架的源码,由于时间和精力限制,我也没有深入研究,我在介绍过程中会给出开源框架的github链接,感兴趣的朋友可以自行去阅读。本文前半部分我想首先介绍这个创新案例的用户故事,后半部分简单描述技术实现。用户故事(User Story)近些年来,诸如人工智能和AR(增强现实)等技术迅猛发展,如何利用好这些先进技术,帮助企业实现数字化转型,是一个值得思考的问题。 某足球制造商想要使用一种高科技的新型材料来制造2018年世界杯使用的足球。这家足球制造商的采购人员找到了一家名叫科创材料的企业,该企业是世界上最先进的足球材料供应商之一。科创材料使用了SAP Sales Cloud系统(SAP Cloud for Customer的Sales模块),希望以此为基础,结合AR,人工智能等前沿技术,打造出一个新的销售工具。这个新的销售工具如何使用呢?我们来看一个具体的使用场景。制造商的采购人员在科创材料的微信公众号上发起会话进行材料咨询。根据制造商的采购员提出的要求,科创材料的人工智能助手推荐了几款合适的材料。比如采购人员希望用一款高科技的原材料生产足球:那么科创材料的数字助手会推送一个公众号图文消息:采购人员点击之后,会看到科创材料的数字助手从SAP Sales Cloud系统后台的产品主数据中进行搜索,返回匹配采购人员要求的6款高科技原材料:为了让采购人员更直观地感受每种新型材料的外观,质地和性能等参数,除了常规的文字和图片介绍外,该销售平台还提供了根据这些原材料制作的成品3D模型展示:以及供客户在移动设备上能实际操作的AR页面,比如体验通过不同材质的皮革制成的足球,在不同场景下的弹力,滚动距离,滚动轨迹的差异等等。点击上图的Test Material按钮进入AR页面进行体验,会询问用户是否授权访问手机摄像头。允许之后,将手机摄像头对准事先准备好的marker(增强现实的实现技术之一,典型的载体是打印了特定图像的一张纸),即可在手机摄像头对准的现实区域内看到一个虚拟的足球。此时采购人员就能在手机上通过手机触动这个虚拟足球的方式,来模拟现实中的踢球动作,以此来体验不同材质制成的足球的各项参数。比如下图显示的是触球后足球的滚动距离和空中运行轨迹。在微信公众号页面里可以做一些简单的配置,选择其中几种材料,以对比的方式显示它们的参数差异。假如采购人员通过初步筛选,发现其中几款材料比较合适,然而对于最后购买哪款犹豫不决,于是该采购人员把经过初步筛选的几款材料通过微信分享给其他同事,让这些同事帮忙甄别,通过投票选出最合适的材料。采购人员点击Create Poll按钮发起投票请求:选中第一,第三和第四款之后,通过微信分享给其他同事所在的微信群里:微信群里的其他同事打开这个分享页面后,点击Vote Materials开始投票,同时可以留言讨论并查看投票结果。等同事们都投完票后,科创材料数字助手自动将投票结果告知采购人员。经过微信群里讨论,大家一致认为应该购买得票数最高的那款原材料。于是采购人员告诉数字助手,决定买2吨 。数字助手通过Sales Cloud的报价单模型,生成了一张包含报价的PDF推送给采购人员:这就是足球制造商的采购人员使用这个创新解决方案的完整流程。我们希望通过这个简单的创新案例,展示出SAP C/4HANA和当今一些新技术相结合,从而帮助企业实现数字化转型,成就智慧企业的可能性。当然,这里选择足球的原材料和成品只是作为一个例子帮助大家更直接地感受到人工智能和增强现实给企业流程管理带来的便利和改善,大家可以自行把足球脑补成其他的物品,比如机械臂,汽车,家电等等。这个创建案例的亮点:(1) 集成SAP Sales Cloud,引导客户完成购买之旅。(2) 利用微信和Recast.AI与客户交互,实现销售过程自动化。(3) 利用AR技术呈现SAP系统内不同产品主数据对应的原材料差异,方便专业人士的验证和体验,加速购买决策流程。以上介绍了这个创新案例的应用场景,下面我们来聊聊技术实现。从开发层面说,该创新案例可分为下图这几个模块:(1) 微信公众号网页端。使得用户可以在微信应用里查看原材料的详细信息,和基于每种原材料制作的成品的3D模型,并提供分享页面,创建投票页面等功能。(2) AR 页面,使用AR的方式,展示各种原材料制成的足球。(3) Proxy Service,又称消息服务器,中间服务器,用于链接微信页面和SAP C4C后台系统,并结合Recast.AI提供智能客服。(4) C4C Backend service(后台服务)增量开发,根据微信用户输入的产品关键字(比如"高科技材料”,搜索系统的产品主数据并返回匹配内容。限于文章篇幅,本文不会深入到代码层面介绍这四个模块的实现,只是简要叙述其原理。对细节感兴趣的朋友欢迎留言私聊。微信公众号网页端网页端就是指前面提过的原材料显示页面,包括3D模型显示页面,投票页面等。我用的框架是Angular,开发了一个单页面应用,它有一个外壳页面index.html,在app.js中创建了AngularJS的module。在config.js中使用Angular的config配置页面以及和页面关联得控制器,配置路由规则,配置渲染和加载规则。这些没什么可说的,毕竟我司和国内的Angular高手数不胜数。其中3D模型的显示我用的是threejs这个基于webGL的JavaScript框架。基于webGL的开源框架,需要支持webGL的浏览器,通过这个框架将3D模型,主要是每种足球原材料的obj 文件,mtl文件和各种纹理图片渲染成最后在微信里看到的不断旋转的3D足球。这些3D模型文件在我的电脑上长这个样:obj文件: 一种开放的几何定义文件格式,它仅表现3D几何体,即顶点的位置,以顶点列表的方式定义每个多边形的顶点,法向量和面的UV坐标,以及纹理顶点。顶点以逆时针存储,不必显式声明法向量。其中obj3.0格式支持多边形(Polygon),直线(Lines),表面(Surfaces),和自由形态曲线(Free-form Curves)。直线和多角形通过它们的点来描述,曲线和表面则根据于它们的控制点和依附于曲线类型的额外信息来定义。这些信息支持规则和不规则的曲线,包括那些基于贝塞尔 (Bezier)曲线,B样条(B-spline),基数(Cardinal/Catmull-Rom样条),和泰勒方程(Taylor equations)的曲线。obj文件的一个例子:mtl文件(Material Library File): 材质库文件,描述的是物体的材质信息,采用ASCII存储,任何文本编辑器可以将其打开和编辑。一个mtl文件可以包含一个或多个材质定义,对于每个材质都有其颜色,纹理和反射贴图的描述,应用于物体的表面和顶点。用作3D物体表面的纹理的各种png图片:这个很好理解。比如下图是某种材质制成的成品足球:那么它对应的纹理文件是这样的:我的任务就是使用threejs的API把这些模型merge在一起,生成最后带有3D视觉效果的JavaScript对象。为了避免让本文成为threejs编程教程,我不展开描述,感兴趣的朋友请查询threejs官网:https://threejs.orgAR页面该页面也是基于另一个增强现实的JavaScript框架AR.js开发的,从github上的Star数目就能看出其受欢迎的程度。https://github.com/jeromeetie…这个页面的具体编码工作是SAP成都研究院数字创新空间在德国的兄弟团队完成的,这里不做更多介绍。微信消息服务器开发一个服务端应用,部署在SAP云平台上(其他云平台也行),然后把服务的url配置到微信公众号的开发者中心中去即可。具体开发方式我之前的C4C同事张航和大卫哥已经做过详细介绍,这里不再重复:SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成而基于Recast.AI的智能客服实现,我的同事Jerry在他的文章 使用Recast.AI创建具有人工智能的聊天机器人 里详细介绍过使用方法。C4C后台服务开发根据用户微信输入的关键字,去C4C系统查找匹配的产品主数据。我们前面视频里显示的6款原材料,在C4C系统主数据配置如下:而关于PDF文件在SAP ABAP Netweaver系统的生成,我的同事Jerry写过很多文章:(1) Convert word document into PDF via Adobe Livecycle Enterprise servicehttps://blogs.sap.com/2013/11…(2) Another way to preview PDF in CRM web client UI with little codinghttps://blogs.sap.com/2013/12…(3) Create Webservice enabled Adobe PDF attachment in CRM Applicationhttps://blogs.sap.com/2014/05…(4) Export WebClient UI table to PDFhttps://blogs.sap.com/2017/05…(5) How to render PDF which displays picture from the image attachment of your custom BOhttps://blogs.sap.com/2017/05…当然,选择SAP系统外的第三方PDF生成方案也是可以的,生成PDF后,将文件的url推送到微信上,用户点击url即可在微信里打开PDF查看内容。这部分后台开发主要是我的同事Liao, Janet(廖婧)完成的,这里表示感谢。这个C/4HANA同人工智能与增强现实技术结合的创新案例就介绍到这,感谢阅读。相关阅读一些SAP Partners能够通过二次开发实现打通C/4HANA和S/4HANA打通C/4HANA和S/4HANA的一个原型开发:智能服务创新案例SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成使用Recast.AI创建具有人工智能的聊天机器人机器学习在SAP Cloud for Customer中的应用在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

January 15, 2019 · 1 min · jiezi

SAP人工智能服务Recast.AI的一个简单例子

关于这个例子的完整介绍,请参考公众号 “汪子熙”的两篇文章:SAP C/4HANA与人工智能和增强现实(AR)技术结合的又一个创新案例和使用Recast.AI创建具有人工智能的聊天机器人:本文介绍如何用Java代码同recast.AI网站上创建好的模型交互。我创建了一个名为get-product-infomation的机器学习模型,用"Add an expression"下面的这么多句子去喂这个模型:一会测试时,我会用这个句子进行测试 " I am looking for some materials", 所以先记下来。如果任意输入一句话,recast.AI识别出来意图为get-product-infomation, 我希望AI自动返回一些句子,这些句子定义在recast.AI模型的Actions标签页下面:比如这个Actions模型的意思是,从Sure, what type of product are you going to produce?和Cool, what products do you want to produce?里随机挑选一句返回。下图右半部份是recast.AI的测试控制台。下面是用Java代码方式消费这个人工智能模型的例子:public class RecastAIService {private final static String RECAST_AI_URL = “https://api.recast.ai/build/v1/dialog";private final static String DEVELOPER_TOKEN = “Token feb6b413a1a8cf8efdd53f48ba1d4”;public Answer dialog(final String content, final String conversationId) throws ClientProtocolException, IOException{CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost postRequest = new HttpPost(RECAST_AI_URL);postRequest.addHeader(“Authorization”, DEVELOPER_TOKEN);postRequest.addHeader(“Content-Type”, “application/json”);String body = “{“message”: {“content”:”"+ content+ “”,“type”:“text”}, “conversation_id”: “"+ conversationId+””}";HttpEntity entity = new StringEntity(body);postRequest.setEntity(entity);HttpResponse response = httpClient.execute(postRequest);if(response.getStatusLine().getStatusCode() == 200){String result = EntityUtils.toString(response.getEntity());JSONObject resultJsonObj = JSON.parseObject(result);JSONObject results = (JSONObject) resultJsonObj.get(“results”);JSONArray messages = results.getJSONArray(“messages”);JSONObject nlp = (JSONObject) results.get(“nlp”);JSONArray intents = nlp.getJSONArray(“intents”);Answer answer = new Answer();if (null != messages && messages.size() > 0){JSONObject messageJson = messages.getJSONObject(0);answer.setContent(messageJson.getString(“content”));}if (null != intents && intents.size() > 0){JSONObject intentJson = intents.getJSONObject(0);answer.setIntent(intentJson.getString(“slug”));}return answer;}logger.debug(“Failed to access recastai. The response code is” + response.getStatusLine().getStatusCode());return null;}测试代码:传入I am looking for some materials,recast.AI解析出这个句子的意图有99%的可能性是get-product-information:Java代码返回的句子也确实是recast.AI模型里维护的回复之一:要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 1 min · jiezi

浅谈SAP Cloud for Sales 自动化

在Jerry还在本科进行计算机理论知识学习时,我曾经把软件开发里的质量工程师(Quality Engineer)理解成是每天只是简单地做着运行开发人员编写好的软件,如果发现问题,通知开发人员去修改这种机械的体力活。后来进入SAP后,观察团队里的质量工程师每天做的事情,才知道我当初简直是很傻很天真。我的两位同事,姚瑶和郑晓霞,之前已经就她们在SAP质量工程师这个岗位上工作的一些体会做了分享:SAP成都研究院姚瑶:软件质量保证工作的变迁SAP成都研究院郑晓霞:Shift Left Testing和软件质量保证的一些思考今天,由Jerry的另一位同事,Tang Minna继续给大家带来SAP标准产品质量控制方面的分享。*大家好, 我是唐敏(Minna Tang),目前是SAP成都研究院C4S(Cloud for Service)团队的质量工程师。除了本职工作以外,我喜欢烹饪苏菜——少了川菜的热烈与厚重,却多了一份自然与纯真;喜欢在图书馆里拜读名人传记——看尽红尘故事之后,静静地感受时光的流逝;闲暇时也喜欢尤克里里——跟随跳动的音符,感受人生的起起落落。今天我想基于目前C4S产品的现状和自身的技术背景,简单聊聊自动化这个动人心魄、让人又爱又恨的话题。相信任何一个软件开发团队的每位成员,听到“自动化”一词,都会抱有热烈的期待。对于老板来说,这个词意味着成本的下降及更高的ROI(Return On Investment,投资回报率);从开发工程师的角度,自动化有助于更早地检测到代码变更对原有功能的影响;测试工程师当然是全力支持自动化的,因为省心和省力;产品经理自然也不会拒绝自动化,因为它能够带来更高效的交付和更快速的迭代。然而,我们身边也不乏自动化实施失败的团队。2013年在我前一家工作的公司里,我曾参与某核心系统项目的开发工作,这个业务系统从需求到完整上线共耗时一年半,核心功能的开发更是耗时大半年之久。面对如此庞大的业务测试成本和强需求,PMO(Project Manage Office)在项目开发之初就启动了自动化测试需求,然而在业务功能不稳定,产品需求、开发与测试基本属于赶工状态的情况下,与人工回归相比,自动化所带来的收益基本微乎其微。所以选择适当的自动化时机和策略,是自动化成功与否的重要因素之一。众所周知,SAP众多产品都在使用自研的ABAP进行开发。当我加入SAP后,我了解到这些运行在ABAP Netweaver之上的产品,均有完备的自动化测试。对于ABAP后台功能代码,主要是开发人员为核心功能编写完备的,覆盖率高的单元测试,然后用事务码SUT调度成后台作业定期执行,如果自动化测试执行时发现故障,会自动发邮件通知相关人员。前台UI代码,无论是原生的Fiori应用还是CRM Web Client UI这种加了一层皮肤的类Fiori应用,都能通过Selenium来进行UI的自动化测试。当然,SAP成都研究院也在进行众多基于微服务架构的云产品开发,主要使用Java编程,那么自动化测试的实现也更加容易,Spring系列框架里有大量成熟和流行的自动化测试套件可供使用。从迭代发布的角度讲,C4S产品的发布周期为一个季度一次,每个季度中有三个周期:前两个周期主要完成新功能开发,第三个周期需要团队成员既完成新功能测试,也需要回归系统原有功能。与此同时,每个季度中还有5次补丁的发布,每一次都需要完成原有业务的回归测试。夹在产品新特性测试和回归测试之间的,是一望无际的工作量和对高效率、高质量测试的需求。我为所在团队负责的功能制定的自动化的策略是: 接口 + UI自动化覆盖。也许您会问,作为一个请求的最前端,既然UI的测试都能覆盖了,那自动化测试为什么还需要接口的覆盖?工作量是否存在重复?从功能的角度来讲,确实有些重复。但从收益的角度来讲,对接口的自动化测试进行投入,收益远超成本。1. 对于任意一个系统,接口的稳定性在整个系统中的重要地位不言而喻。相对于后置的E2E(端到端)测试,接口测试能够从基础层减小变更对整个应用及下游业务调用方的影响范围。2. 同时,接口的测试也能为UI自动化实施提供基础数据。UI自动化为了完成某个场景的测试,通常会有很多前置业务数据的依赖。这些UI自动化需要的测试数据如何生成?有同事建议可以提前手工造数据。如果自动化测试的数据都要依靠手工来维护,在我看来,这个自动化不要也罢。通常,在接口测试完成之后会将已测试通过的接口封装成工具类,供后续UI自动化的工程化调用,这样既减少了UI自动化的数据依赖,对接口测试通过率也提出了更高的要求。所以一般的接口工程必须100%通过,才能完成触发后续UI自动化的作用去执行功能测试。3. 为性能测试准备打下坚实的基础。通常准备性能测试之前,接口测试的响应时间会成为反馈接口性能的重要依据。我们在制定接口性能的SLA(Service-Level Agreement)时,其基本数据来源就是接口测试。而很多互联网公司,相对于端到端的响应时间,他们更注重接口的响应时间,因为接口更底层。尤其针对多层接口依赖的系统,每年 618,双11之前的线上大促压测,接口全链路测试必定是重中之重。我在C4S推荐使用的接口测试框架为Spring + Maven + Testng,语言为Java, 被测对象为C4S oData服务提供的HTTP API。其中Spring框架主要负责通过注解方式完成对象注入,Maven负责工程结构和Jar包管理,Testng负责具体的测试工作。对于不熟悉Java的朋友来说,借助现有工具诸如Postman也能很好地胜任这项工作。1. 工程结构及说明接口主体工程以Maven规范工程为模板,所有的代码和相关资源文件均放置在src/test目录下。工程模块主要分为4部分:测试代码、枚举对象、工具类及相关资源文件。测试代码:这是测试代码的主要存放目录。 通常根据业务的不同,我们将每一个接口的测试案例按照业务测试和参数测试分别编写。所谓业务测试,是指测试案例中涉及业务规则的部分。比如,某接口中存在一个channel(渠道)字段。业务规则定义:当channel为all时,创建全渠道使用的数据;当channel为特定值时,创建的数据只能适用于特定的场景。则业务测试的案例有2个:o Channel = allo Channel = 特定数据参数测试:主要测试接口参数字段是否为必填项。比如,某接口中存在一个channel为必填字段且必须为指定枚举类型字符串,当传入接口为null或blank或非枚举值时,框架返回HTTP 400参数错误,同时提示错误信息。此时参数测试案例有3个:o Channel = nullo Channel = “”(blank)o Channel = “XXXX”(XXXX为非枚举值)枚举对象:此部分是将业务中经常用到的固定参数使用枚举的方式列出,方便整个工程使用。见下图中httpEnum文件夹中的类。工具类:包括基本工具类和业务工具类部分。业务工具类是将特定接口进行封装,方便下游接口调用使用。资源文件:包括Spring相关配置,properties文件以及参数测试中的数据来源文件等。2. 案例编写此处以实现oData的SocialMediaActivity 接口的自动化测试为例来进行说明。我们借用颜值大师——李晓刚老师画的图来大致了解SociaMediaActivity在C4S微信集成架构中的作用:由上图所知,C4S通过暴露SocialMediaActivity接口来方便Agent调用。在C4S和Social Media集成的相关场景中,用户可以通过关注微信公众号来绑定一个特定的BusinessPartner(以下简称BP), 从而达到通过用户在系统中自定义的微信Channel来直接与C4C服务模块中的工作人员直接交互的目的。而Activity是针对指定的BP所进行的活动,例如创建ticket,点赞,回复等。故而完整的业务流程如下:获取系统token获取已关联的BP信息创建ticket信息评论/点赞/回复操作 数据清理BeforeClass: 执行获取token的准备工作。BeforeMethod: 创建/获取已关联的BP信息。Test: 特定业务的测试案例。本处对Activity的层级和操作内容进行检查,因此有2个测试方法。AfterMethod:清理已创建的Activity。此处需要重点说明是,为避免后台错误数据对应用正常使用的影响,每一次执行都需要对增量数据进行清除处理,保持环境干净整洁。AfterClass: 清理创建的BP信息。3. CI(Continuous Integration, 持续集成)基于Maven工程的集成,本例中使用Jenkins进行示例,与此同时项目工程中需要使用surefire-plugin(一个用来执行测试用例的Maven插件)来配置相关的测试案例范围。在pom.xml中配置testng.xml文件:testng.xml文件内容示例:使用Maven的好处再次体现,只需要简单配置即可使用:在Jenkins中加入testng report plugin展示,然后build即可。虽然我更擅长使用基于Java的Selenium这个UI自动化框架,也明白接口测试完成之后,对UI自动化的巨大帮助,但由于C4S在印度和美国团队内都使用现有的成型产品SAHI,所以这里我只介绍SAHI在C4S的应用。SAHI是Tyto Software旗下的一个基于业务的Web应用自动化测试工具, 通过注入 JavaScript来访问 Web 页面中的元素。相对于Selenium等自动化测试工具,SAHI在动态 ID元素查找和隐式页面等待处理等方面具有一定的优势。感兴趣的同事可前往官网进行尝试。1. 工程结构及说明此处以Social 案例为例:DD_CSV: 案例运行的的数据来源Function_Library: 该目录中存放已封装的基本共用函数,如登录、登出、工作中心访问、表格访问等。更加细致的封装则是将页面元素抽象到Library中的IDS下,便于统一管理, 如下图:SCRIPTS:特定的UI测试案例。SUITE:测试案例运行的范围。2. 案例编写此处以RUI项目中SingleTab功能为例进行说明。MultiTab和SingleTab功能是指在C4S产品中,当用户在全屏模式下打开某一个或多个工作视图时,系统会将多个工作视图以Tab的形式显示在工作区中;但是当用户修改浏览器大小到一定尺寸后,工作区中将只显示活动的那个Tab。 MultiTab显示时,有活动与非活动Tab之分,同时要适配多个Tab的鼠标操作切换和通过功能菜单的切换。如下图所示:SingleTab显示:只显示当前活动的Tab,在显示数据和形式上与MultiTab有差别,同时也要适配通过功能菜单的Tab切换。与此同时,该特性需要测试系统在不同的主题、字体大小下此特性也能正常工作。因此测试案例的流程如下(可参考代码注释部分): (1) 重置相关特性:浏览器大小,主题,字体大小,视图类型,页面默认过滤器(2) 访问特定的工作视图并显示特定数据,验证全屏模式下活动状态的/非活动状态的MultiTab的显示和Tab上数据的正确性(3) 缩小浏览器大小:验证Tab上数据正确性修改系统主题,验证SingleTab的显示修改字体大小,验证SingleTab显示3. CI集成基于Jenkins的强大的插件功能,C4S通过将Jenkins与GTP(内部缺陷管理平台)的集成完成CI调度和运行。UI自动化的CI集成,使得C4S产品的回归测试的效率大大提升。以今年8月份发布的版本为例,手工回归的测试案例目前已接近7000个。如前文所述,诸多的测试案例在每个迭代中持续的回归测试,则是一项耗时又耗力的工程。而且这仅仅只针对回归测试所执行的案例。从手工回归测试案例的数量不难看出,快速反馈系统功能状态机制在持续交付链中的重要性。而在对接口进行全覆盖测试之后,对UI自动化覆盖回归测试主流程的需求也愈加强烈。在C4S,我们借助Jenkins 并行测试完成UI自动化,并使用邮件通知测试结果。在节省人工回归成本的同时,使得产品管理团队能够在短时间内快速、全面了解系统功能的运行情况,并给与团队成员质量的信心。与此同时,在出现模块功能失效甚至是系统宕机时,这种快速反馈链的建立为开发人员尽早尽快修复问题争取了时间,减少了后续修复的时间成本。就目前的测试覆盖需求而言,由内到外的接口覆盖及端到端的UI覆盖,在满足底层稳定可靠的同时,也保证前端功能的可用性。对于SAP质量工程师而言,工作内容远非测试工作这一项内容,从团队成员质量意识的提升到单元测试覆盖及检查;从测试工作到团队质量反馈,都是SAP质量工程师在每日工作中需要去花心思琢磨的。而从团队利益着手,考虑每一项质量活动的价值和意义,对质量工程师来说是一项全局观的考验,也是一场质量与效率的平衡。以上就是我今天关于C4S自动化的分享,如有疑问或进一步探讨,欢迎联系我们,感谢阅读。相关阅读SAP成都研究院姚瑶:软件质量保证工作的变迁SAP成都研究院郑晓霞:Shift Left Testing和软件质量保证的一些思考要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 1 min · jiezi

SAP S/4HANA使用ABAP获得生产订单的状态

在S/4HANA里,我们如何根据一个销售订单的行项目,查看对应的生产订单状态?双击行项目:点击Schedule line:这里就能看到生产订单的ID和状态了。其中订单的状态存储在表vsaufk里,注意订单和状态可以是1对多的关系。状态的ID和描述信息存储在表tj02t里,所以有了下面的代码:METHOD get_prod_order_status.DATA: lt_status TYPE TABLE OF j_status,lt_text TYPE TABLE OF tj02t,lv_id LIKE iv_prod_order_id,ls_result LIKE LINE OF rt_status_in_s4_format.lv_id = iv_prod_order_id.CALL FUNCTION ‘CONVERSION_EXIT_ALPHA_INPUT’EXPORTINGinput = lv_idIMPORTINGoutput = lv_id.SELECT stat INTO TABLE lt_status FROM vsaufk WHERE inact = space ANDaufnr = lv_id.CHECK sy-subrc = 0.SELECT * INTO TABLE lt_text FROM tj02t FOR ALL ENTRIES IN lt_statusWHERE istat = lt_status-table_line AND spras = ‘EN’.LOOP AT lt_text ASSIGNING FIELD-SYMBOL(<text>).CLEAR: ls_result.ls_result-status_id = <text>-istat.ls_result-status_code = <text>-txt04.ls_result-status_text = <text>-txt30.APPEND ls_result TO rt_status_in_s4_format.ENDLOOP.ENDMETHOD.测试一下,成功拿到所有状态,和事务码CO03里看到的一样。要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 1 min · jiezi

使用nodejs代码在SAP C4C里创建Individual customer

需求:使用nodejs代码在SAP Cloud for Customer里创建Individual customer实例。代码:var createAndBind = require(’../jerryapp/service/createAccountinC4C.js’);createAndBind(“o0KlM1i2_4-zHRmDk-IWGRlA1Cjc”);上述代码基于微信open IDo0KlM1i2_4-zHRmDk-IWGRlA1Cjc在系统里创建一个Individual customer。createAccountinC4C.js的具体实现在Jerry的github上:https://github.com/i042416/wechat/blob/master/jerryapp/service/createAccountInC4C.js在命令提示行里输入命令node createAccountAndSocialProfile.js:上述代码会自动在系统里创建Individual customer,并打印出ID:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

一个SAP开发人员的2018年终总结

我是SAP成都研究院的Jerry Wang,我喂自己袋盐。时间过得真快,2017年发生的事情还历历在目,一转眼,2018年又马上要结束了。Jerry惊恐地发现,随着年龄的增长,时光流逝的速度仿佛有加快的趋势。因此,年终的记录显得更为重要。把自己一年做的无论工作还是生活上的事情梳理一遍,若干年后来回味,一定非常有意思。2017年,Jerry的工作和生活,可以用这两个关键字概括:编程和游泳。更多详情可以参阅我的文章:Jerry的2017, 编程与游泳2018年,我的关键字变成了:编程与自媒体。Jerry是怎么想起在2018年,尝试着写微信公众号文章的呢?这要从很久很久以前说起。Jerry是2007年1月进入SAP成都研究院的。工作一两年之后,平时做开发遇到技术问题,我要么就请教身边的资深同事,要么就用即时通讯软件请教SAP其他地区的同事,像上海,德国,以色列这些地方的同事。当时SAP内部用的还是Messenger(用过这个软件的朋友们估计都有一把年纪了)。一个偶然的机会,我在Google上搜索一个技术问题时,发现了一个称为SDN的网站, SAP Developer Network。我惊讶地发现,这个网站上的其他网友,使用的编程语言和我每天工作中使用的一样都是ABAP,并且上面既有提问和解答,也有专门的技术博客。当时我的感受,就像阿里巴巴发现了芝麻开门这句咒语一样。从那一天起,我每天工作之余,都会花一些时间浏览SDN,遇到有网友提问而我知道线索的,我会去回答;看到别人写的好的技术博客,我会精读。一段时间过后,我觉得SDN帮助我提升了自己的技术,是时候从一个单纯的内容索取者(content consumer)转变成内容生产者(content producer)了。在我当时的老板Posei的鼓励下,我从2013年写下第一篇博客,从SDN改版成SCN(SAP Community Network), 再到如今的SAP Community,我始终保持了在上面写英文博客的习惯。我想,去年SAP Community的组委会让我成为SAP Mentor, 可能并不是我写的这630篇博客内容有多优质,而是对我这些年这份坚持的一种肯定。再说到微信公众号,一个IT从业人员非常熟悉的,获取知识和讯息的平台。Jerry关注了很多技术公众号,阅读完作者的文章之后,总是习惯把文章里面的知识和技巧自己动手做一做,想办法融合到工作中去。https://github.com/i042416我的github上有三个仓库,分别存放了ABAP,JavaScript和Java的代码片段。这些片段是我读了高手们的微信公众号文章后,把高手们在文章中传达的思路融入到SAP应用开发中而成。我通过这种方式,把微信公众号文章读到的知识,真正融合成自己知识体系的一部分。Jerry觉得这种学习方式有点像鸟山明《龙珠》里描述的沙鲁和魔人布欧,他们都是通过不断融合其他高手来提高自己的战斗力。再回到我想开始写微信公众号文章的原因:1. 微信公众号上别人的文章看得多了,自然而然的,我同样问自己:为什么你不在上面贡献点原创的东西呢?2. 去年年底正好读了昔日Airbnb女神朱赟的一篇文章,提到她开始写公众号文章之后,对自己工作和生活产生的一些积极改变。我当时很羡慕女神朱赟在业界的影响力,超高的人气和广阔的人脉。然而,光是羡慕别人,有用么?3. 我在之前的文章 SAP成都研究院35岁以上的开发人员都去哪儿了? 里提到,我是一个工作上很需要新鲜感的开发人员,喜欢不断尝试和挑战新的未知事物。在我每一篇微信文章写好之后点击群发按钮之前,我都无法预知我的关注者会做出怎样的评价。这种新鲜感是我想要的。综合以上三点,就有了我今天这个公众号。当然我除了要感谢SAP成都研究院其他肯赏脸在这个公众号上写文章的同事之外,也要感谢SAP中国研究院宽松的氛围和我的各级领导们对这件事情的大力支持。他们不但没有觉得我在业余时间做这件事情是不务正业,而且还帮助我转发这些文章,让它们能够传播得更广。2018年这个公众号总共发了87篇文章,其中我自己写了55篇,其余的文章是Jerry在SAP成都研究院的23位同事贡献的:SAP成都研究院2018年总共87篇技术文章合集Jerry一篇文章的平均写作时间是3小时,那么55篇的总共时间是165小时。这165个小时全是Jerry下班后的业余时间,如果按一周工作40小时计算,那就是4周多一点。由此可见,这55篇文章花费了Jerry相当一部分业余时间,不过好在我还是坚持了一整年。在2019年,我的更新频率或许不如今年,因为我可能会有其他新鲜事物要去尝试。能够给员工充分提供这种自由度让他/她们能够分享出自己的专长,无怪乎每年SAP中国研究院都会赢得各种最佳雇主的奖项。当然自媒体不仅仅局限于微信公众号。Jerry也经常浏览知乎,不过看得最多的还是讲游泳练习的文章和游戏发烧友的技术分享。2018年我在知乎上也获得了525个关注,456个赞同和809次文章收藏。我最初接触简书,同样是搜索游泳技术文章,通过百度发现了这个平台。除了收获636个粉丝和1603个喜欢之外,简书还有个贴心的功能,统计文章总字数。不知不觉中我已写下46万字了?CSDN:ITPub:腾讯云社区:阿里云栖社区的编辑专门给我创建了一个云栖社区的公众号:InWeHub:这里也要感谢ITPub,腾讯云,阿里云栖社区和InWeHub四位编辑今年对我的帮助和支持,祝你们2019年工作一切顺利。2018年的自媒体经历就说到这里。今年是我接触游泳的第三个年头。虽然我按照原计划学会了自由泳,但我只会右侧换气。我希望在2019年学会双侧换气。今年除了继续在Labs里窝着之外,还是抓住了机会到几个客户那里跑了几趟。今年3月的时候:5月跑了两家:刚刚过去的12月,作为一个成都人,Jerry见识了沈阳的大雪。去之前,听闻温柔可爱的小姐姐Carol告诉我工厂车间里没有空调和暖气,不过幸好我运气不错,去的那几天沈阳一点也不冷,最冷也就零下几度左右。六月份的时候,感谢Cissy主持的Toast Master,让我在公司里过了一把玩棍的瘾,也因此认识了SAP成都研究院的国家二级运动员,能双手使棍的Haytham Xu。更多Haytham和我与双截棍背后的故事,请参考这两篇文章:一个SAP开发人员的双截棍之路SAP成都研究院许聚龙:Hello, Coresystems!最后,让我用回答问题的方式,结束这篇流水账似的年终总结。在微信公众号后台,我时常收到一些提问,有这几种类型:你是如何从一个毕业生成长为SAP技术专家的?你是如何处理技术深度和技术广度这二者的平衡的?我是一个开发人员,工作5年了,感觉自己技术没啥长进,到瓶颈期了。你为什么有那么多的东西可以写成文章?首先我需要申明的是,Jerry不是那些业界上成名已久的大佬,和向我提问的各位一样,我只是一个普通的开发人员,大家问的很多类似上面列举的这种非技术问题,其实我也给予不了太多的帮助。我能给大家分享的是自己的一个习惯。在工作中我处理一些特别复杂的技术问题时,喜欢把思路用笔涂鸦在笔记本上,后来我才知道,这种做法有个时髦的名字:思维导图。在我做开发的时候,我脑子也在高速运转, 边写代码边想一些问题,比如:1. 我正在实现的这个功能,我记得今天上班地铁上看到一个高手的博客里介绍的一个解法更简捷高效。我把这件事情记在本子上,等忙完了去研究高手的解法。2. 我正在实现的这个功能,调用这几个API之后,或者在Spring/Maven里, 或者在yaml, xml, json这些配置文件里做几个配置就OK了,我的任务是完成了,然而这些API/配置为什么能够工作?背后的原理是什么?我把这些疑问记在本子上,等忙完了去研究。3. 当一个技术问题折腾了我很长时间才解决之后,我会在本子上写下反思:为什么我一开始没找到正确的突破口,浪费了这么多调试的时间?是知识有欠缺,还是一开始思路就错了?为什么会造成这种思路错误的现象?下次有办法避免吗?4. 我现在工作在SAP产品A上,我参与开发的这个功能,在SAP产品B和C上也都支持。这些需求类似的功能,在SAP产品A,B和C上的技术实现,因为其产品本身技术架构的区别而存在差异。那么把这个功能在A,B和C上的实现做个横向比较,优缺点各是什么?把这个比较的任务记在本子上,等忙完了去研究。时间一长,我的笔记本上就记下了很多这种零散的内容。经过我的归纳和整理,最后的输出就是我在SAP Community和自媒体平台上的技术文章了。我在SAP工作12年,总共写满了16本笔记本,叠在一起大概22厘米高。回到上面那些在公众号后台向我提出的问题,如果让我用四个字作答,我的答案就是做到:专注,坚持。2018年还有几十个小时就将永远离开我们了。在过去的一年,我要感谢我的父母,妻子和儿子,感谢我的亲人对我工作的支持;我要感谢我的领导Posei,感谢他对我职业生涯发展规划的建议和我工作中犯下错误的宽容;我要感谢和我一块写公众号文章的成都同事们,感谢SAP成都研究院C4C团队的每一位同事(的美食),感谢一块合作过的上海同事们;我要感谢关注我微信公众号,给我留言提问的朋友们;我要感谢各大社区和我保持长期联系,辛勤工作的编辑们;我要感谢一有优惠活动,第一时间想到我的健身顾问们;在即将到来的2019年里,Jerry预祝大家一切都好。我是SAP成都研究院的Jerry Wang,我喂自己袋盐。我们2019年再见。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

SAP Cloud for Customer销售订单External Note的建模细节

SAP Cloud for Customer的销售订单创建页面里,我们可以给一个订单维护External Note,当这个订单同步到S/4HANA生成对应的生产订单后,这个note可以作为备注提示生产工人。它的建模逻辑是:首先进入调试模式,查看到这个字段绑定到UI模型的TextCollection/CustomerInformation上然后进入Cloud Application Studio,找到UI模型这个字段,查看发现它又绑定到了BO的TextByTextTypeCodeAndLanguageCode.这里不难猜测出,SAP C4C BO上支持多种类型的note,通过typecode区分。那么我怎么知道External Note对应的typecode的值呢?这个好办,在系统里维护一条带有External note数据的销售订单,比如这条:然后通过OData读取这条销售订单,OData url如下:https://jerry.sap/c4c/odata/c…‘00163E7209B31EE98297C038F2A3FDDC’)/CustomerQuoteText响应里包含的字段TypeCode的值10024就是External Note的type code。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 15, 2019 · 1 min · jiezi

SAP成都研究院2018年总共87篇技术文章合集

2018年很快就要结束了。Jerry在2017年年底准备开始写这个公众号时,给自己定的目标是:2018年至少保证每周发布一篇高质量的文章。如今2018年就快过去了,高质量与否需要大家来反馈,至少从量上看,已经达到我订的目标了。当然这87篇技术文章,有31篇文章是Jerry的成都研究院同事贡献的,在这里对这些同事表示感谢。按照名字的字母顺序,依次感谢:Chen VickyDeng SunHe AndrewLi BenLiao JanetMa HongboPeng SunShinePing JingJingSong HaoTang MinnaWang CongWen AvivaWu DavidXia JasonXu BorisXu HaythamYang JoeyYao YoyoZhang HarryZhang JonathanZhang SeanZheng KateZhou Shuai下面是文章列表。文章后面如果未跟作者名字,则默认作者是Jerry本人。这个视频是我的同事,Zhou Shuai用他的无人机完成的SAP成都研究院大楼的航拍,欢迎广大SAP同仁来访问参观。1. Jerry的CDS view自学系列 2. Jerry的通过CDS view + Smart Template 开发Fiori应用的blog合集3. Jerry的ABAP, Java和JavaScript乱炖4. C4C和微信集成系列教程5. Jerry的2017, 编程与游泳6. Jerry的UI5框架代码自学教程 1/1/20187. Jerry的碎碎念:SAPUI5, Angular, React和Vue 1/2/20188. ABAP开发人员未来应该学些什么 1/3/20189. Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现 1/5/201810. SAP的这三款CRM解决方案,您能区分清楚么 1/6/201811. SAP Fiori应用的三种部署方式 1/8/201812. 关于S/4HANA里Sales Office 和Sales Organization那些事儿 1/10/2018 Zhang Sean13. SAP成都研究院35岁以上的开发人员都去哪儿了? 1/13/201814. Jerry的WebClient UI 42篇原创文章合集 1/14/201815. Jerry的CRM Middleware(中间件)文章合集 1/16/201816. 从产品展示页面谈谈Hybris的特有概念和设计结构 1/17/2018 Zhang Jonathan17. 阿里云上到底能运行SAP哪些产品? 1/19/201818. Jerry的ABAP原创技术文章合集 1/21/201819. Jerry的Fiori原创文章合集 1/26/201820. OAuth 2.0协议在SAP产品中的应用 2/3/201821. 从产品展示页面谈谈Hybris系列之二: DTO, Converter和Populator 2/10/2018 Zhang Jonathan22. Hello World, S/4HANA for Customer Management 1.0 2/28/201823. 从程序猿到SAP产品经理,我是如何转型的?(上篇)3/11/2018 Xia Jason24. 从程序猿到SAP产品经理,我是如何转型的?(下篇)3/18/2018 Xia Jason25. 那些年我用过的SAP IDE 3/24/201826. SAP S4CRM vs C4C, 诸葛亮和周瑜? 3/30/201827. SAP成都C4C小李探花:浅谈Fiori Design Guidelines 4/8/2018 Zhou Shuai28. Jerry和您聊聊Chrome开发者工具 4/15/201829. SAP成都研究院李三郎:SCP Application Router简介 4/22/2018 Li Ben30. Jerry眼中的SAP客户数据模型 4/28/201831. 300行ABAP代码实现一个最简单的区块链原型 5/3/201832. SAP UI和Salesforce UI开发漫谈 5/8/201833. 汶川大地震中的SAP成都研究院 5/12/201834. SAP成都研究院的体育故事 5/13/2018 Deng Sun35. 使用Java程序消费SAP Leonardo的机器学习API 5/14/201836. 使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数 5/16/201837. 使用JDBC操作SAP云平台上的HANA数据库 5/18/201838. 用JavaScript访问SAP云平台上的服务遇到跨域问题该怎么办 5/23/201839. 金庸和古龙,Netweaver和微服务,以及SAP Hybris Revenue Cloud 5/25/2018 Chen Vicky40. SAP成都研究院马洪波:提升学习力,增强竞争力,收获一生乐趣 5/27/2018 Ma, Hongbo41. SAP Cloud for Customer 使用SAP UI5的独特之处 5/30/2018 Yang Joey42. 一个SAP顾问在美国的这些年 6/2/2018 Song Hao43. SAP成都研究院菜园子小哥王聪:当我用UI5诊断工具时我用些什么 6/4/2018 Wang Cong44. 写在Github被微软收购之际 - Github的那些另类用法 6/5/201845. 在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务 6/7/201846. 企业数字化转型与SAP云平台 6/10/201847. SAP UI 搜索分页技术 6/16/2018 Wang Cong48. SAP OData编程指南 6/18/201849. SAP数据中心概述 6/23/201850. SAP成都研究院飞机哥:程序猿和飞机的不解之缘 6/24/2018 Zhang Harry51. SAP成都研究院DevOps那些事 6/30/2018 Ping, Jingjing52. ABAP vs Java, 蛙泳 vs 自由泳 7/3/201853. SAP产品的Field Extensibility 7/14/201854. SAP Cloud for Customer Extensibility的设计与实现 7/21/2018 Xu Boris55. 从产品展示页面谈谈Hybris系列之三:Hybris Service层介绍 7/28/2018 Zhang Jonathan56. SAP成都研究院姚瑶:软件质量保证工作的变迁 8/3/2018 Yao Yoyo57. SAP移动应用解决方案之一:HTML5应用 + Cordova = 平台相关的混合应用 8/8/2018 Yang Joey58. 使用Recast.AI创建具有人工智能的聊天机器人 8/9/201859. SAP成都研究院安德鲁:自己动手开发一个Chrome Extension 8/18/2018 He Andrew60. 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图 8/21/201861. 一个SAP开发人员的双截棍之路 8/22/201862. 机器学习在SAP Cloud for Customer中的应用 8/26/201863. 你的项目刚刚启动?是时候考虑Globalization了!9/1/2018 Wang Cong64. 聊聊C语言和ABAP 9/7/201865. SAP成都研究院郑晓霞:Shift Left Testing和软件质量保证的一些思考 9/13/2018 Zheng Kate66. Hyperledger Fabric on SAP Cloud Platform 9/16/2018 Wen Aviva67. SAP云平台,区块链,超级账本和智能合约 9/18/201868. 动手使用ABAP Channel开发一些小工具,提升日常工作效率 9/22/201869. 打通C/4HANA和S/4HANA的一个原型开发:智能服务创新案例 9/26/201870. 我用ABAP做过的那些无聊的事情 9/29/201871. 不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧 10/8/201872. SAP成都研究院数字创新空间沟通S/4HANA和C/4HANA的智能服务演示视频和Coresystems分享预告 10/13/201873. SAP成都研究院许聚龙:Hello, Coresystems!10/17/2018 Xu Hathyam74. SAP成都研究院Sunshine: 我的C4C实习感受和保研之路 10/25/2018 Peng, Sunshine75. Jerry的知识星球:SAP中国神秘奶牛关卡 10/29/201876. 金庸的武侠世界和SAP的江湖 11/1/201877. 加入Jerry的知识星球,共同讨论SAP技术 11/3/201878. SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成 11/7/2018 Wu David79. SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成 11/12/2018 Zhang Harry80. 站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma 11/18/201881. SAP S4CRM 1811 服务订单API介绍 11/24/2018 Song Hao82. 在Kubernetes上运行SAP UI5应用(上)12/2/201883. 在Kubernetes上运行SAP UI5应用(下) 12/4/201884. 一些SAP Partners能够通过二次开发实现打通C/4HANA和S/4HANA的方法介绍 12/7/201885. SAP成都研究院廖婧:SAP C4C社交媒体集成概述 12/8/2018 Liao Janet86. SAP Fiori + Vue = ?12/18/201887. 浅谈SAP C4S自动化 12/25/2018 Tang Minna要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 2 min · jiezi

基于SAP Kyma的订单编排增强介绍

尽管有一万个舍不得,2018年还是无可挽回地离我们远去了。唯有SAP成都研究院的同事和我去年在网络上留下的这些痕迹,能证明2018年我们曾经很认真地去度过每一天:SAP成都研究院2018年总共87篇技术文章合集一个SAP开发人员的2018年终总结今天写的这篇文章也是因为工作需要。本文会首先介绍SAP传统产品里的订单编排增强技术,再来了解一下同样的增强需求,SAP Kyma是如何完成的。目录基于SAP传统ABAP技术的订单编排增强技术基于SAP Kyma的订单编排增强技术SAP产品里的订单处理流程,无论是On-Premises解决方案还是云产品,我认为归根到底可以概括成四个字:订单编排,包含两个层次的内容:1. 单个订单通过业务流程或者工作流驱动的状态迁移,比如从初始的Created状态,经过一系列操作,最后进入Closed状态;2. 多种类型的订单协同工作,完成一个完整的端到端业务流程。典型的例子有销售自动化(Sales Force Automation)里的从Lead, Opportunity, Quotation到Contract,Order这些不同类型的订单协同。SAP系统里订单状态的迁移到底有多复杂?复杂度绝对远超初学者的想象。以SAP CRM为例,在我使用的SAP CRM 714系统里,订单状态总共有906种,这不得不让人佩服SAP CRM当初的设计者考虑问题的周全。即便已经设计了这九百零几种状态,SAP仍然考虑到了客户可能的状态扩展需求,因此采用了一种经典的User Status(用户自定义状态)和System Status(SAP标准状态)的两层状态设计,让用户能够随便定义的User Status通过扮演中间层角色的Business Transaction,映射到能够被SAP标准程序所感知的System Status。上图左边的Open, In process, Released和Completed就是用户自定义订单状态,SAP允许客户给每个状态分配一个Low和High的值,通过这两个值巧妙地提供了一种用非图形化方式进行状态跳转的功能。比如In process状态的Low为20,意味着In process状态不可能重新回到Open状态,因为Open状态的ID 10小于In process状态的Low字段定义的20——一个状态能跳转到的目标状态的ID,必须位于由该字段的Low和High定义的区间内。除了复杂的状态处理和跳转外,SAP订单编排的复杂度主要体现在以下方面:1. 很多SAP的客户,除了购买SAP的On-Premises产品或者订阅云服务外,还拥有其他业务系统。这类客户的订单编排,在SAP标准业务流程基础上往往还存在和这些第三方业务系统的交互。2. 即使是同一行业的客户群,因为地域和国家,语言的差异,可能业务流程也存在一定的区别。SAP发布的标准功能有时无法100%支持这些在细节上存在千差万别的业务流程。因此SAP系统对订单编排增强的支持就非常必要。当然,不同的SAP产品,对订单增强的实现方式也各不相同。在SAP CRM里,虽然SAP没有明确提出Business Object这个概念,但订单应用基于的模型实际上仍然是由不同的节点组成:每个节点对应一些更底层的模型节点,其上可以注册各种事件处理函数。下图是Service Request这个BO的抬头节点的事件处理函数:每种事件触发时,注册的函数会自动执行。每个节点可以分配一个或多个执行函数。当然,严谨的德国人在最简单的观察-发布者模式上又添加了几个维度的设置。下图第一列红色的Execution Time,表示这些分配的函数到底是事件触发后立即执行,还是延迟到订单抬头或者行项目的通用例程执行完后再执行(往往用于实现批量操作,或者待执行函数同通用例程存在依赖关系,或者出于性能考虑)。第二列的Priority,即函数执行优先级,如果若干函数除了优先级外其他维度维护的属性完全一致,则按优先级从高到低依次执行。第三列Event,就是观察者-发布者模式里的事件了,下面是SAP CRM订单框架一些标准的事件:最后一列就是事件监听函数。Jerry倾向于把CRM订单处理系统的运作方式理解成类似下图这种复杂的水管传输系统,订单业务流程依次通过注册在不同事件上的监听函数去执行,就像水从这一根根大小粗细长短各异的水管流过一样。如果客户对其中某个业务步骤需要做增强(需要替换某根水管), 只需要用一个自己实现的函数去替换SAP标准函数(自己另外找一根水管替换掉现在正在工作的水管),能替换的前提是自己实现的函数的接口同被替换函数完全一致(自己另外找的水管和以前的水管两端接口的规格完全一致)。而SAP Cloud for Customer里的订单模型,其Business Object在目前最新的1811版本里仍然是由ESF2框架实现,只是后台对Partners不可见,但大家可以类比SAP On-Premises世界里的BOPF框架,两个框架的实现原理类似。在Cloud世界里,想对订单处理流程做增强,同之前介绍的SAP CRM相比,相对来说受的限制要多一些。在Partner做增强开发的Cloud Application Studio里,所有能做增强的点以Hook的方式显示如下:Partners可以在这些Hook里进行业务功能增强开发。有些Hook可能存在某些读写限制,比如AfterLoading这个Hook,会在SAP BO的标准加载逻辑执行完毕后被调用,在这个Hook的实现里,SAP不允许任何对BO节点标准字段的写操作,以避免Partners的增强对SAP标准流程可能带来的影响。有的顾问朋友可能会说,这些Hook不就是SAP Netweaver里传统的Business AddIn(BAdI)么?没错,概念上可以这么理解,需要提醒的就是,这些Hook创建之后,在ABAP后台并不是以BAdI Implementation的方式存储,而是以ESF2 Determination的方式存储,类似下图这种BOPF里的Determination:我们再来了解一下用SAP Kyma如何完成类似的需求。在使用Kyma之前,大家得对Kyma是什么,SAP为什么要开发出Kyma这两个问题比较清楚才行。我之前的文章 站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma 已经介绍了这两个问题的答案,所以本文不再重复,直接上实例了。我们假设需要对SAP Hybris Commerce的下单流程做增强,在标准的Fraud(欺诈)检查里加入我们在Kyma里实现的自定义检查流程。如下图所示,其中浅蓝色的矩形框代表我们用Kyma实现的自定义Fraud检查逻辑。具体增强了哪些检查逻辑呢?从下的订单里拿到下订单的客户ID,然后在Kyma里调用SAP Marketing Cloud和SAP云平台上提供的服务对这个客户做校验,Kyma拿到校验结果后,再传回Commerce。下面是具体步骤。1. 首先登录Commerce的back office页面,定义一个新的action,ID为EXTERNAL_KYMA_FRAUD_CHECK。做过ABAP开发的朋友们不难理解这个action,可以类比成ABAP里的action profile,用于存储和维护Partner的增强。2. 进到Kyma的console页面:选择一个stage进去,点击Lambdas进入编辑页面:新建一个Lambda function,取名fraudcheck2。我们所有的增强逻辑就写在这个函数里。这个函数自动创建的标签(Labels),Kubernetes老司机们一定觉得很亲切。这些标签其实和大家现实工作中使用云笔记里的标签,以及图片管理软件里的标签作用相同,就是一种键值对(Key Value Pair), 可以允许用户将Kubernetes对象进行灵活分组,并提供高效的检索。这个标签的概念不是Kyma发明的,而是Kubernetes的标准功能。Function Trigger里可以指定这些Lambda函数在哪些事件触发后执行,思路和前文介绍的SAP CRM函数注册一致。选择第一步定义了新的action后对应的event:关于Lambda函数具体的实现,做过nodejs开发的朋友们一定不会觉得陌生。首先第18行,19行从event这个输入参数对象里取得发生事件的订单Code,然后第26行消费OCC(Omni Commerce Channel)Restul API获得订单明细,从明细里获得订单的客户ID,再调用第30行的代码根据客户ID拿到客户明细,然后使用第37行和第40行的代码分别检查该客户的邮箱地址是否有效,以及该客户是否第一次下单。注意第43行和46行的代码我暂时注释掉,稍后才会启用。现在我们来测试一下。在Commerce里下一个单,记下订单ID 2139。回到Commerce back office页面,查看刚才下的订单的Business Process,输入2139进行查询:这里根据ID EXTERNAL_KYMA_FRAUD_CHECK进行搜索,找到了刚才第一步新建的基于Kyma action对应的流程日志记录:我们再去查看这个订单的Fraud检查记录:点这个Fraud Reports查看检查结果。这个标签从左到右依次排开的风格很像Fiori和ABAP Webdynpro。可以看见前文介绍的Email有效性检查和是否是首单的检查结果。Email检查结果:客户的邮箱地址有效。首单检查返回的分数是100,根据当前Commerce配置文件这个结果被认定为首单。具体配置文件的位置和本文主题无关,这里不详述。现在再回到Kyma的Lambda函数编辑器里,将之前注释掉的从Marketing Cloud获取联系人地址的函数以及调用SAP云平台的Business Partner服务的函数重新启用:启用之后,保存,然后进入Service Catalog。这个组件也是Kubernetes提供的标准组件,Kyma基于它做了增强,能够将第三方的服务导入进来给Kyma的Lambda函数消费。这里能看到已经导入了很多第三方服务。我们其实可以把这个界面类比成SAP云平台的Service Market Place。选择SAP云平台的Business Partner Service:接下来的步骤和我们在SAP云平台上消费一个服务类似,首先创建一个服务实例:然后再基于这个服务实例创建一个绑定,绑定类型设置成Function Binding,绑定的目标设置成之前编辑好的Lambda函数。现在再下一个单试试,下单客户选择同第一个订单相同的客户:这一次,这个第二次下的订单的Fraud检查报告,同第一个订单相比就多了两条记录:首先看第二条首单检查的记录,得分为0,和我们期望的结果一致,因为这已经不是该客户第一次下单了:从Marketing Cloud的服务返回的检查结果:从SAP云平台的Business Partner服务返回的结果可以看出,下单的这个客户不存在一个对应的Business Partner。本文这个例子,在Commerce下单流程中通过Kyma去访问Marketing Cloud和SAP云平台上的服务进行额外的Fraud检查,业务上来说可能意义不大,更多的是从技术的角度出发,介绍了这种基于微服务架构的订单编排增强方式。祝大家新年快乐! 相关阅读站在巨人肩膀上的牛顿:Kubernetes和SAP Kyma在Kubernetes上运行SAP UI5应用(上)在Kubernetes上运行SAP UI5应用(下)要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

January 15, 2019 · 1 min · jiezi

SAP Cloud for Customer里Sales Order和Sales Quote的建模方式

SAP Cloud for Customer的Sales工作中心里有Sales Quote和Sales Order两个视图,一个用于销售报价单,另一个用于销售订单。流程上是先有报价单 ,报价单是一份OFFER,并不具备法律效力,只有在生成销售订单后,即买卖双方都对报价单上的内容进行一些协商后,达成一致生成的最终订单,才具有法律效力。现在我需要搞清楚Sales Order这个视图的UI是基于哪个Business object创建的。SAP C4C的UI都是基于MVC pattern设计的,首先在Chrome开发者工具里找到UI的模型名称:/BYD_COD/SalesOnDemand/SalesOrder/UI/COD_SALESORDER_TI.TI.uicomponent到cloud Application Studio的UI Designer里打开这个UI 模型,在Data model区域找到Business object的名称为CustomerQuote,这就有点怪了,我起初以为是Sales Order。后来在CustomerQuote这个BO上发现一个字段叫做TypeCode,才知道Sales Order和Sales Quote这两个业务模型底层的技术模型都是共享CustomerQuote这个BO,可以通过TypeCode来区分。typecode为30,代表这是个Sales Quote:typecode为2059代表是一个Sales Order:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

January 13, 2019 · 1 min · jiezi

SAP Cloud for Customer Sales Order Requested Date的业务含义和实现

我们在创建Sales order销售订单时,需要指定一个RequestedDate:这个字段绑定到了BO字段:CustomerQuote.RequestedFulfillmentPeriod.TimePointPeriod.StartTimePoint.DateTime这是一个0-1的BO内部的association:为什么Requested Date总是比创建日期晚两天呢?是在这里配置的:2 Days意思就是比创建日期晚2天抬头的Requested Date的值会通过C4C BO后台的determination复制给行项目Schedline line的同名字段。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

December 21, 2018 · 1 min · jiezi

SAP Fiori + Vue = ?

2017年3月28日,我到国内一个SAP CRM客户那里,同他们的架构师关于二次开发的UI框架选择SAP UI5还是Vue进行了一番探讨。回到SAP研究院之后,我把这个问题扔到了公司的微信群里,引起了大家的热烈讨论。因为出差回来之后,我需要向我老板和老板的老板汇报工作,因此写了这篇blog:https://blogs.sap.com/2017/03…时光飞逝,转眼间2018年也快过完了。今天上午上班路上,忽然看到阳哥在公司微信群里发了一个截图,提供了一个指向公网github仓库的链接:https://github.com/SAP/fundam…看到这个仓库的url,Jerry马上就想起了早些时候在experience.sap.com网站上看到的这条新闻:https://experience.sap.com/ne…我们都知道Fiori代表SAP新一代UI的界面风格,而UI5是Fiori UX(User Experience,用户体验)的具体实现技术。SAP决定将Fiori同具体UI实现技术解耦, 是出于什么考虑呢?众所周知,前端技术发展的速度是非常快的,新理念,新名词,新工具层出不穷,很多前端开发程序猿经常哀叹"学不过来了",那么,如果只绑定于某一种具体的UI实现技术,Fiori UX会缺乏足够的灵活性,很难充分利用业界最新技术来更好地为终端用户服务。同时,这一举动也充分体现了SAP确实在倾听自己生态圈里开发人员的呼声,通过这种解耦允许SAP开发人员根据实际项目需要,灵活选择最佳UI框架来开发Fiori应用。Fiori UX同底层UI实现框架解耦的关键就在于SAP Fiori Fundamentals, 一个轻量级的展现层实现。从技术层面上说,SAP Fiori Fundamentals不是一种新的UI技术或者框架,而是一系列stylesheets和HTML标签的集合,以此来让SAP生态圈里的UI开发人员用其喜欢的UI框架,比如Angular,React,Vue等进行开发,同时自动保证开发出的应用仍具有Fiori的风格和用户体验。SAP Fiori Fundamentals的出现,绝不意味着它会替代UI5,实际上,SAP对于UI5的维护和功能增强一直没有停步。按照Jerry文章的风格,当然是到上代码的时候了。因为Jerry所在的团队进行原型开发,组内同事大多喜欢用Vue,所以我们就来试试SAP Fiori Fundamentals + Vue这对组合。首先我们得有一个能工作的Vue应用,然后在此基础上加工。您可以在我的SAP博客上找到一个Hello World的Vue应用,通过webpack打包之后运行,能在浏览器里看到显示的Hello World:https://blogs.sap.com/2017/12…这个Hello world的Vue应用,项目结构如下:下面我们在其基础上进行加工。1. 在项目文件夹下安装fundamental-vue。这是为SAP Fiori Fundamentals实现的一个轻量级的Vue组件集合。npm install –save fundamental-vue安装完毕后在package.json里能够看到fundamental-vue还在beta版,这一点和SAP在github上的文档描述一致。2. 下面这个链接罗列了SAP Fiori Fundamentals里支持的Vue组件,同时也介绍了如何自定义一个新的Vue组件。https://dist-4d2gqwr8y.now.sh…下图是一个Table组件的运行时效果,大家不难发现这个Table的外观和我们之前用UI5开发的很相似。点击Show Code,会显示这个Table组件的Vue实现源代码,类似我们UI5 Toolkit里显示的控件在UI5 XML View里的源代码,道理是相通的。把这一大堆代码粘贴到我们Vue应用src文件夹下的index.vue里:同样在index.vue里,在module.exports里实现作为Button事件处理函数addCurrentEntry, 以及硬编码一些测试数据:在main.js里加入两行:import FundamentalVue from ‘fundamental-vue’;Vue.use(FundamentalVue);最后一步,在index.html里引入位于CDN上的Fiori Fundamentals的css文件。当然github上也提到了也可以使用npm install –save fiori-fundamentals将其安装到本地使用。至此加工就结束了。用webpack打包之后,运行npm run dev启动wepack-dev-server, 就可以在localhost里看到如下效果:输入新的谋士姓名,点击Add Entry按钮之后能将其输入到表格中。尽管网上有种说法,“郭嘉不死,卧龙不出”,然而孔明永远是Jerry心中的三国演义第一谋士。这个使用Vue组件开发而成的具有Fiori UX风格的应用运行时效果,大家可以查看这个视频体验:<iframe frameborder=“0” width=“677” height=“380.8125” allow=“autoplay; fullscreen” allowfullscreen=“true” src=“https://v.qq.com/txp/iframe/p...;amp;vid=q0814wlsmqn&amp;autoplay=false&amp;full=true&amp;show1080p=false&amp;isDebugIframe=false" style=“margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"></iframe>或者查看我托管到github上的demo:http://i042416.github.io/Fior…手机上打开上面链接的效果:由于时间关系,Jerry还没能深入了解SAP Fiori Fundamentals的更多技术细节,只是简单给大家展示了它和Vue协同工作的效果。未来如果有机会,Jerry会给大家带来更多深入报道,感谢阅读。相关阅读SAP Fiori应用的三种部署方式Jerry的Fiori原创文章合集SAP成都C4C小李探花:浅谈Fiori Design GuidelinesJerry和您聊聊Chrome开发者工具Jerry的UI5框架代码自学教程Jerry的碎碎念:SAPUI5, Angular, React和VueSAP Cloud for Customer 使用SAP UI5的独特之处当我用UI5诊断工具时我用些什么在Kubernetes上运行SAP UI5应用(上)在Kubernetes上运行SAP UI5应用(下)要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

December 21, 2018 · 1 min · jiezi

SAP CRM settype的创建,背后发生了什么

来自我的同事Sara。当我们在CRM系统里创建一个settype之后,其实系统后台悄悄的帮我们创建了很多ABAP对象,比如对应的database tables, other ABAP Dictionary objects, function groups, function modules, and screens等等。Create set types:DB check:自动创建了一个和settype ID同名的数据库表问题:How this DB generate?How to check what function groups, function modules, and screens are created? Especially which screens?When we assign the attributes to the set type, I guess it will insert lines into the table.Jerry的解答:当你创建一个新的settype时,product框架会自动生成针对该settype的structure和存储Table, 以及对应的用于CRUD的function module。但是了解框架本身如何实现我前面说的这些事情,对我们接下来做的co deployment没有直接帮助。你的这个问题可以转换成:假设我只知道product的description字段是通过某个settype实现的,我想不问别人,自己弄清楚该settype的名字和访问该settype的CRUD的function module名字,该如何做?I got one information from my colleague, the Product Description function is implemented by the SAP standard set type. Then I want to make clear:(1) Which standard set type implement Product Description and it’s DB table?(2) Which function module (API) implement the CRUD of Product Description?写在前面:本文提及的方法只限一种思路,不排除个别Assignment Block 不适用的情景,请大家广开思路,积极探索更多的方法来研究,希望能总结出更多的具体API,简化每一个功能的实现。Product ID: SZIPC (in QHD)After this self study, I can get a general knowledge of how the product fields implemented in the SAP System.Then I will start this self study step-by-step by question driven.(1) Which standard set type implement Product Description?Try Google it first. Wow, got some information. set type name COMM_PR_SHTEXT.(2) Is it right? How can I display set type?One way, Google.Second way, I would like to use SE93 to find transaction code by transaction description, got it!TCODE: COMM_SETTYPEThere is some issue, you can not display set type by TCODE: COMM_SETTYPE directly, you can only use COMM_ATTRSET input the set type COMM_PR_SHTEXT first the sue TCODE: COMM_SETTYPE to dispaly.(3) Then how can I find the DB for this set type and the CRUD function model?There is 2 ways.The first way, is to use TCODE: ST05 trace.I update the description from Material_Sara to Material_SaraZhang. I search with key words ‘Material_SaraZhang’, then I find the DB–COMM_PORTEXT.The second way, I would like to use TCODE: SE93 find the package of TCODE COMM_SETTYPE.–Assume,I do not know, Most of the Set Type name = DB Table name.There must be a table include all the Set Type name and DB Table names, how can I find it?This is an important thinking point, for every TCODE in SAP, it’s a collection of multiple functions /tables/views. Which should be packaged in a package.In the package, there is multiple DB, from the DB description, you can know COMC_SETTYPE is the admin table which include all information we want.–Admin table and header table always as the start and base point of DB relationship.Filter by the set type name COMM_PR_SHTEXT, we found the set type DB COMM_PRSHTEXT and related function module.(4) How the function module work when I read the product description?TCODE: SE37 find COM_COMM_PR_SHTEXT_READ_WITH_P and set breakpoint.search Product ID: SZIPCin WebClient UI.Follow the call stack, find the key API for read product set types.(5) How the function module work when I Update the product description?Function Module: COM_COMM_PR_SHTEXT_MAINTAIN_UPFollow the call stack, find the key API for update product set types.(6) I will try to simplify this function module, pick this function into a report for confirming how does this CALL FUNCTION ‘CRM_PRODUCT_UI_GETDETAIL’ work?This is the key function for processing product set types.We’d better to understand it’s indeed input valueOne, is product guid in a structure.Two, is the set type name.It means that, any set type can read by this function.要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

December 21, 2018 · 3 min · jiezi