Salesforce平台支持多租户Multi tenant的核心设计思路

Multitenancy is the fundamental technology that clouds use to share IT resources cost-efficiently and securely.多租户支持是所有云服务提供商都需要着力实现的一种技术,用于云基础设施上在成本可控和保证安全性的前提下进行IT资源分享。多租户支持面临的四大挑战:how to keep tenant-specific data secure in a shared database so that one tenant can’t see another tenant’s data?如何保证共享数据库内不同租户间的数据隔离,通俗的说,一个租户不应该看到其他租户的数据。当一个租户对其拥有的schema对象或者应用编程接口进行调整时,不应影响到其他租户的功能和整个系统的可用性。How can one tenant customize various schema objects and an application’s user interface in real time without affecting the functionality or availability of the system for all other tenants?How can the system’s code base be patched or upgraded without breaking tenant-specific schemas?系统基层实现发生变动,比如代码版本升级,或者新的补丁进来时,不应该破坏每个租户私有的对象。And how will the system’s response time scale as tens of thousands of tenants use the service?随着系统租户数量的增加,整个系统的响应时间不应该急剧下降。Force.com’s core technology uses a runtime engine that materializes all application data from metadata—data about the data itself. In Force.com’s well-defined metadata-driven architecture, there is a clear separation of the compiled runtime database engine (kernel), tenant data, and the metadata that describes each application. These distinct boundaries make it possible to independently update the system kernel and tenant-specific applications and schemas, with virtually no risk of one affecting the others.Salesforce应对这些挑战的设计是,采取了一种运行时引擎的思路,所有的应用数据都通过元数据生成,即所谓元数据驱动的架构(metadata driven architecture)。这样一来,模型的元数据作为输入,交给运行时引擎加工,生成运行时使用的模型和数据,三者各司其职,有严格的区分,实现了一种高度动态的内核。注:本文的英文文字和图片来自Salesforce官网:https://developer.salesforce….中文文字为本文作者原创内容。要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

SAP ABAP里数据库表的Storage Parameters从哪里来的

如何查看ABAP数据库表的storage parameter?事务码SE11,utilities->Database Object->Database Utility:点这个Storage Parameters:上面SAPGUI里显示的数据实际来自HANA数据库里的System view:TABLES, 使用如下的SQL语句就能查询到COMM_PORODUCT的storage parameters(存储参数了):SELECT *FROM “SYS”.“TABLES"WHERE SCHEMA_NAME = ‘SAPAG3’ AND TABLE_NAME = ‘COMM_PRODUCT’要获取更多Jerry的原创文章,请关注公众号"汪子熙”:

February 14, 2019 · 1 min · jiezi

Salesforce和SAP HANA的元数据访问加速

Salesforce在Jerry的其他文章曾经提到,Salesforce里运行时对象均是通过静态存储的元数据,经过Runtime engine加工而成的。Because metadata is a key ingredient of Force.com applications, the system’s runtime engine must optimize access to metadata; otherwise, frequent metadata access would prevent the service from scaling. 既然元数据在salesforce平台中扮演了如此重要的角色,那么运行时引擎对元数据的高效访问就成为一个重中之重的话题,如果达不到这个目标,频繁的元数据低效访问将无法保证平台上提供服务的高扩展性 high scalability。With this potential bottleneck in mind, Force.com uses massive and sophisticated metadata caches to maintain the most recently used metadata in memory, avoid performance-sapping disk I/O and code recompilations, and improve application response times.Salesforce平台设计了很多复杂的元数据缓存机制,确保最近访问过的元数据驻留在内存里,避免了磁盘IO的开销和代码的重编译,从而确保整个应用的响应时间不会影响元数据访问受到影响。SAPABAP Netweaver也有类似的设计,把很多需要高效访问的数据特别是应用程序的元数据存储到应用服务器的shared memory共享内存里。使用事务码SHMM查看shared memory内容:SAP HANA里还能通过系统视图system view M_METADATA_CACHE_STATISTICS来对元数据的缓存访问进行分析:要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

S/4HANA服务订单Service Order的批量创建

我工作中接到一个任务,需要在性能测试系统里创建一亿条服务订单service order来做性能测试。这么大规模的数据量,当然只能用代码来创建了。本文提到的所有ABAP代码,我均已上传到我的Github上了:https://github.com/i042416/KnowlegeRepository/tree/master/ABAP/S4This document provides guide about how to generate a large volume of service order ( confirmation ) and service request test data in S4CRM performance test system for performance measurement purpose.The data is generated based on a series of ABAP reports. ZCRMS4_CREATE_MATERIAL_OPTPattern for material number: prefix for generated material ID. Take above screenshot for example, once executed, you will get a series of materials with the following material ID:Pattern for short text: for example if you specify “Android phone S”, you will get the following description pattern:ZCRMS4_HOME_CREATE_BPSZCRMS4_HOME_CREATE_ORDER_LOOPThis report is used to create a large number of Service Orders.Order description: define the description pattern of created service orders.For example, the input parameter in the above screenshot will lead to the created orders with the following description patterns:Max number of created items: if you specify an integer N, a random number among 1 ~ N of line items will be created for each Service order.Max item quantity value: if you specify an integer N, the line item quantity value will be assigned with a random integer among 1 ~ N.Material Number Range:Let’s say you have first created 10000 materials with ID prefix as “ANDROID”, which means now in table MARA you already have 10000 records with ID starting from ANDROID00000000001 and ending with ANDROID00000010000.Now in this report, you specify Material Number Range as ANDROID00000000001 and ANDROID00000010000, so that when this report create a new line item, it will randomly pick up a material among this material repository and assigned to created line item.Sold-to party range: behaves the same as Material Number Range. You have to first create a series of business partners and write down their ID prefix, for example you create 100 BP with prefix BCP. Then maintain Sold-to party range as BCP0000000001 to BCP0000000100. This report will randomly pick one among the 100 BP and assigned it as the Sold to party in Service Order’s header level.ZCRMS4_HOME_CREATE_SR_LOOPUsed for Service Request mass data generation. The input parameter behaves the same as ZCRMS4_HOME_CREATE_ORDER_LOOP.During the period that those reports are running, you can use report ZTABLESIZE to check the number of created records currently. This report will list table name, table record number and table storage size accordingly.You are supposed to run these reports via background job to avoid TIME OUT issue.Please do not occupy ALL Background work processors so that the normal system operation like TR import are not hindered.要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 2 min · jiezi

S/4HANA生产订单的标准状态和透明工厂原型状态的映射

事务码CO03查看生产订单的状态:从下面的界面能看出S/4HANA里生产订单在任意时刻可能存在多个状态:生产订单的ID和状态ID的关系是1:N,维护在数据库表VSAUFK里:如何把上述SAP系统标准状态映射到透明工厂原型的5个状态去呢?目前的映射实现采取的是“关键状态法”:只要生产订单的状态里包含I0048 - distributed to MES, 就认为该订单处于组装状态只要生产订单的状态里包含I0012 - distributed to MES, 就认为该订单处于已交货状态如果C4C创建的销售订单还未同步到S/4HANA,或者虽然同步到S/4HANA,但是S/4HANA的生产订单尚未创建完成,即下图右边灰色区域的时间窗口所示,此时如果查询生产订单状态,API会返回状态排队中.也就是说,app里尚存在两个状态,“加工”和“检测”,在S/4HANA生产订单里找不到对应可映射的标准状态。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 14, 2019 · 1 min · jiezi

SAPGUI系统登录页面配置的SAProuter有什么用

大家在安装完SAPGUI后,准备添加系统列表进行登录时,注意过这个SAProuter字段么?从SAP的帮助文档上可以找到SAProuter的定义:https://help.sap.com/saphelp_…SAProuter is an SAP program that acts as an intermediate station (proxy) in a network connection between SAP systems, or between SAP systems and external networks. SAProuter controls the access to your network, and, as such, is a useful enhancement to an existing firewall system (port filter).Figuratively, the firewall forms an impenetrable “wall”around your network. However, since particular types of connections need to penetrate this wall, a “gate”has to be made in the firewall. SAProuter assumes control of this gate.In short, SAProuter provides you with the means of controlling access to your SAP system.SAProuter是一个SAP发布的应用,在SAP系统与系统之间,SAP系统与外部网络之间扮演着代理的角色。SAProuter能实现对SAP系统的访问控制,是企业防火墙的有效补充。如下图所示,部署于企业局域网的客户端SAPGUI进行系统登录,登录请求通过局域网内的SAP router转发到Internet网络上的另一台SAP Router,再转发给部署于企业内网的ERP服务器。上述描述的场景里,形象的说好比在ERP服务器所在的企业内网和SAPGUI的客户端所在的内网打了两个洞,在洞里部署两台SAP router确保只有受限的网络请求能够进出这两个被防火墙保护的安全网络。这种“打洞”的思路在SAP另一款解决方案:SAP cloud connector里有类似的用法:详情参考我的文章:使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数:https://www.jianshu.com/p/3f2…我们可以把用SAPGUI登录系统的快捷方式保存到本地,下次双击即可直接用SAPGUI登入系统:用记事本打开,发现这些.sap文件的内容如下:我们主要观看红色高亮部分。H表示主机名,S表示服务Service。要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

SAP云平台对Kubernetes的支持

截至本文发稿(2019-2-10, 农历大年初六)时为止,访问SAP云平台的官方网站:https://cloudplatform.sap.com…能看到下面的网页:SAP云平台上的Kubernetes环境,Coming Soon(即将推出)Build powerful container-native applications and deploy them on a cloud or infrastructure of your choice without worrying about the creation and management of the underlying container clusters.我来翻译一下:SAP云平台的Kubernetes编程环境能让编程人员开发功能强大的容器原生应用并顺利部署在云上,而不用担心底层容器集群的创建和管理。为什么SAP云平台要选择支持Kubernetes?Containers are rapidly becoming a popular development paradigm for cloud-native applications in the industry – with Kubernetes as the dominant container orchestrations technology. The SAP Cloud Platform Kubernetes environment reduces pain points associated with the creation and management of Kubernetes clusters by offering an easy to use, secure and open standards-based Cluster-as-a-Service running on top of a variety of underlying infrastructure choices, deployment options of cloud vs. on-premise, etc. SAP is making this innovation accessible to the entire developer community via an open-source project called Gardener.SAP给出的答案是:基于Kubernetes的容器编排技术近年来已经成为行业里最流行的云原生应用开发范式之一。SAP云平台的Kubernetes编程环境提供了一种简易,安全,基于业界标准的方式提供了对Kubernetes集群的创建和管理,这种方式基于Cluster-as-a-Service(集群即服务)的方式运作,能运行在多种底层云技术设施上,解决了开发人员需要花大量时间学习Kubernetes底层细节的痛点。这种Cluster-as-a-Service的服务,SAP通过开源项目Gardener提供访问:https://gardener.cloud/更多Gardener的使用方式和截图,请参考我的文章:站在巨人肩膀上的牛顿:Kubernetes和SAP Kymahttps://www.jianshu.com/p/c85…使用SAP云平台的Kubernetes编程环境能享受哪些收益Customers can rely upon the SAP Cloud Platform to create, manage, secure and maintain the container clusters for them.客户可以直接使用SAP云平台创建和管理容器集群Leverage the Gardener open-source project to easily access a variety of community innovations.借助Gardener这个开源项目享受到开源社区的种种创新Use container-native development to build and operate complex, stateful cloud applications that require greater freedom over underlying infrastructure.通常情况下开发复杂的云原生应用和有状态的云应用,需要对底层云的基础设施具有很高的自由度。而SAP云平台通过Gardener提供的Cluster-as-a-Service, 给使用者提供了这种自由度。要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

为什么S/4HANA的生产订单创建后会自动release

在S/4HANA系统里我们观察到通过函数CO_61_ORDER_EDIT创建的生产订单会自动释放Release:通过第86行的IF语句的条件检测不难找到原因。变量PROFILE_TMP的类型为TCO43:这个scheduling profile的配置在路径Production->Shop Floor Control->Master Data->Define Production Scheduling Profile里:如下图所示:Automatic Actions标签页里的On Creation->Release勾选中,意思就是Production Order创建后自动释放。要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 14, 2019 · 1 min · jiezi

为什么S/4HANA的销售订单创建会触发生产订单的创建

调用S/4HANA销售订单创建函数SD_SALES_DOCU_MAINTAIN创建一个销售订单时,会触发生产订单的创建。销售订单的每个行项目对应一个独立的生产订单,SD_SALES_DOCU_MAINTAIN相当于CRM里的CRM_ORDER_MAINTAIN,在LOOP里处理每一个行项目:观察这个函数内部的调用栈,发现一个subroutine EIGENFERTIGUNG_BEARBEITEN.:EIGENFERTIGUNG的意思是Own production:BEARBEITEN的意思是TO EDIT:在这个增强里,硬编码了通过Production order maintain的函数CO_61_ORDER_EDIT去创建production order的逻辑:要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 14, 2019 · 1 min · jiezi

如何给SAP C4C的产品主数据division配置出新的下拉选项

如图:C4C产品主数据division字段默认的下拉菜单选项:切换成调试模式,找到UI这个字段绑定的模型字段名称:/Root/MaterialDivision:再找到这个UI模型字段绑定到的core BO字段:Material.Common.MaterialDivisionCode: 进入Business Configuration的Activity List,找到Division的配置:在这里添加一行新纪录:03-沈阳自动所产品线要获取更多Jerry的原创文章,请关注公众号"汪子熙":

February 14, 2019 · 1 min · jiezi

什么是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

使用简单的Java代码在SAP C4C里创建销售订单

需要创建的销售订单的明细通过硬编码指定:比如销售订单的描述为Jerry Test 2019-1-23 16:05PM执行之后,看到Status Code 201,说明创建成功:到UI上能看到成功创建的销售订单:实现代码:package odata;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.URI;import org.apache.http.HttpEntity;import org.apache.http.HttpHost;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.HttpClientBuilder;public class SimpleOrderCreator { private final String SERVICEURL = “https://my5000jerry.c4c.saphybriscloud.cn/sap/c4c/odata/cust/v1/zjerrysalesorder/CustomerQuoteCollection"; HttpClient m_httpClient; private HttpClient getHttpClient() { if (this.m_httpClient == null) { this.m_httpClient = HttpClientBuilder.create().build(); } return this.m_httpClient; } private String getCSRFToken(){ final HttpGet get = new HttpGet(SERVICEURL); get.setHeader(“Authorization”, “Basic 0FOR0pFUlJZMTpTYXB0ZXN0MQ==”); get.setHeader(“x-csrf-token”, “fetch”); HttpHost proxy = new HttpHost(“proxy.sha.sap.corp”, 8080, “http”); RequestConfig config = RequestConfig.custom().setProxy(proxy).build(); get.setConfig(config); HttpResponse response; String token = null; try { response = getHttpClient().execute(get); /Header[] header = response.getAllHeaders(); for( int i =0; i < header.length; i++){ System.out.println(“Header: " + header[i].getValue()); }/ token = response.getFirstHeader(“x-csrf-token”).getValue(); System.out.println(“token: " + token); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException | UnsupportedOperationException e) { e.printStackTrace(); } return token; } private void createSO(String token,String body) { final HttpPost post = new HttpPost( URI.create(SERVICEURL)); post.setHeader(“Authorization”, “Basic 0FOR0pFUlJZMTpTYXB0ZXN0MQ==”); post.setHeader(“Content-Type”, “application/json”); post.setHeader(“X-CSRF-Token”, token); HttpEntity entity = null; try { entity = new StringEntity(body); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } post.setEntity(entity); HttpResponse response = null; try { response = getHttpClient().execute(post); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(“Response statusCode for Batch => " + response.getStatusLine().getStatusCode()); } public static void main(String[] args) { SimpleOrderCreator tool = new SimpleOrderCreator(); String token = tool.getCSRFToken(); String body = “{” + “"Name": "Jerry Test 2019-1-23 16:05PM",” + “"TypeCode": "2059",” + “"BuyerID":"ee",” + “"PartyID":"60102", " + “"CustomerQuoteText":[{” + “"Text": "test comment by Jerry Wang", " + “"TypeCode": "10024"” + “}],” + “"CustomerQuoteItem":[{ " + “"ProductID": "1042416"” + “}],” + “"CustomerQuoteItemProposal":[{” + “"ProductUUID": "00163E72-09C6-1EE8-BBDC-AC5F0CB0D795",” + “"Quantity": "1",” + “"unitCode": "EA"” + “}]” + “}”; tool.createSO(token, body); }}要获取更多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

自开发Web应用和SAP Customer Data Cloud Identity服务的集成

今天的文章继续由SAP成都研究院的云时代女王,Aviva给大家分享关于SAP Customer Data Cloud的一些使用经验。Aviva之前的文章可以在本文末尾处获得。下面是她的正文。*大家好,我是Aviva。本人在SAP不负责Gigya的开发工作,只是出于个人兴趣,在业余时间阅读了SAP官网上Gigya的帮助文档后,就Gigya提供的网站登录接入功能做了一些非常简单的Hello World级别的例子,在此分享给大家。2017年SAP收购了以色列创业公司Gigya, 现在Gigya又被称作SAP Customer Data Cloud,是SAP C/4HANA的五朵云之一。所以下文在不同的上下文出现的SAP Customer Data Cloud和Gigya,大家可以认为这两组词表达的是同一个意思。文章分为两部分,第一部分,简单介绍SAP Customer Data Cloud的业务,第二部分用一个demo介绍如何在自己的网站中使用SAP Customer Data Cloud中的某些服务。Customer Data Cloud从功能上分为三大模块:SAP Customer IdentitySAP Customer ConsentSAP Customer Profile我们首先来简单了解一下这三大功能模块。SAP Customer Identity提供跨渠道和跨设备的用户身份识别,在Web,移动设备和物联网设备上提供统一的注册,身份验证,登录等用户体验。除此之外,SAP Customer Identity还提供单点登录,无密码的身份验证,能够安全地识别来自任何接入端的在线访问者。通过抓取客户授权的身份数据,SAP Customer Identity可以推动个性化、即时营销、销售和服务,同时尊重消费者隐私并满足数据保护法规。Gigya 在安全上做了很多工作,确保用户数据不被窃取和攻击。SAP Customer Consent提供了开箱即用的工作流程,帮助企业明确提出各项服务条款,隐私政策,营销沟通,以及其他需要用户授权的同意请求等等。每次企业更新服务条款和隐私政策,SAP Customer Consent会自动触发新的用户同意请求,并记录每次用户的同意选项和授权的时间。企业管理员可以访问用户整个使用周期内每一次授权的历史记录,从而有效地解决政府对隐私的监管和审计。在企业的数字生态系统中,通过将用户的配置文件与企业的应用程序和服务同步,在每个渠道上强制执行用户的隐私许可,满足关键数据隐私要求。SAP Customer Consent提供了跨平台和跨设备的用户隐私设置服务中心,使用户在整个使用产品的生命周期内,都能透明地管理自己的偏好设置,控制企业对自己的隐私数据的访问规则,从而帮助企业和客户建立透明可信任的关系。SAP Customer Profile通过抓取用户授权后的第一手数据,SAP Customer Profile为用户建立丰富的用户档案,让企业的每个应用程序和服务都可以无缝的使用它们。企业各种应用和服务的用户资料通过统一的平台对管理员开放,同时也能为营销人员提供各种用户数据的分析报告,以及为客户细分和个性化的营销方案提供数据支撑。下面通过一个简单的demo,向大家介绍如何将SAP Customer Identity集成到我们自己的Web应用中。我开发了一个基于nodejs的Web应用。后台使用nodejs + express框架,前端使用SAP UI5。登陆SAP Customer Data Cloud的RAAS(Registration-as-a-Service)平台。首先在RAAS平台上创建site和应用。本地开发和测试使用的Site Domain可以填成localhost:创建一个新的Application:创建了Site 和Application之后,Site会自动生成对应的API Key:Application会产生User Key和Secret。其次,在Web应用的index.html中引入Gigya Web SDK:<script src=“https://cdns.gigya.com/js/gigya.js?apikey=YOUR-API-KEY-HERE"></script>然后使用SAP UI5开发Web应用的登录页面 login.view.xml和控制器login.controller.js。Gigya 提供了一个默认的用户登录注册页面,只需两行代码就可以在我们的Web应用里使用。这种便捷的使用方式体现了RAAS的含义。在xml视图中嵌入一个div标签:在控制器实现的初始化函数中加入:gigya.accounts.showScreenSet({ screenSet: ‘Default-RegistrationLogin’, containerID: me.byId(‘LoginGigya’).sId });Gigya的登录和注册服务就加入我们自己的Web应用中去了。除了使用默认的登录屏幕设置之外,我们当然可以直接在Gigya平台上定制登录页面和注册流程。Gigya提供了UI Builder,在UI Builder里可以使用默认的控件,通过拖拽就可以生成不同的登录页面(类似SAP Cloud for Customer UI Designer),也可以直接修改html和css,修改登录和注册流程等等。Gigya定义了许多不同类型的事件,这些事件由用户交互来触发,例如用户登录,按钮点击等。应用程序可以注册监听感兴趣的事件,并在收到这些事件时执行代码。下面是简单的监听用户登录和注销事件的代码:var me = this;gigya.accounts.addEventHandlers({ onLogin: me.login, onLogout: me.onLogout, context: me });登录后,在控制台简单地打印一些字符串。login: function (response) { console.log(“LOGIN!!!!!!!!!!!!!!!!!”); console.log(response);**},关于Gigya支持的所有事件和事件相关参数,可以参考用户手册:https://developers.gigya.com/…在Web应用后台,我们还可以使用Rest API的方式访问Gigya的相关服务。举个例子,在后台获取用户的Account信息,调用Rest API 需要用到Site 的API Key 和Application的User Key和Secret。以上只是基于Gigya提供的服务进行的一些最简单的练习。关于Gigya更多的功能介绍,请移步官网上去查看,有很详细的介绍:https://developers.gigya.com/ 感谢阅读。Aviva另外两篇文章:Hyperledger Fabric on SAP Cloud PlatformSAP C/4HANA与人工智能和增强现实(AR)技术结合的又一个创新案例要获取更多Jerry的原创文章,请关注公众号"汪子熙”: ...

January 22, 2019 · 1 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专家培训之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 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

容器,Docker, Kubernetes和Kyma,以及Kyma对SAP的意义

大家好,今天非常高兴能给大家做一个关于Kyma的技术分享。这个session的audience主要是针对使用咱们成都研究院使用Java和nodejs等技术栈做微服务开发的同事们。对于在ABAP netweaver上做SAP传统开发的同事们来说,这个session可以让大家开阔一下眼界。这是今天session的agenda:•Why Containers?•Relationship between Containers and Dockers?•Why Kubernetes?•Relationship between Kyma and Kubernetes•A real example: Commerce cloud extension via Kyma之所以要在Kyma真正开始前做容器,Docker,Kubernetes的铺垫,是因为Kyma基于Kubernetes,而Kubernetes又是容器编排框架,Docker又是一种流行的容器运行时实现技术,如果不提Kubernetes,Docker和容器,没有接触过这些概念的同事一定会觉得一头雾水。我们先来看容器。我们说任何技术都有其使用场景和解决的痛点。那么为什么这些年来容器技术非常火呢?得益于近些年微服务架构的火热,很多企业包括SAP自己也在开发基于微服务架构的新应用,比如在坐很多同事所在团队正在做的事情。而基于微服务架构的SaaS软件开发,业界有一套标准,或者说是最佳实践,那就是著名的twelve-factor标准:https://12factor.net/zh_cn/而容器,就是一种有助于开发人员以更小的代价去开发一个满足这12个准则的基于微服务架构的云原生应用的技术。比如这个准则里提到的,微服务应用的build,release和运行阶段应该严格区分,应用通过一个或多个无状态的进程进行执行,彼此隔离,通过进程模型进行水平扩展,等等,这些通过容器技术都可轻易实现,不需要开发人员付出额外代价。因此,我们需要记住一个结论,容器的使用场景,永远是和微服务架构,SaaS,云原生应用这些紧密相连的。那么容器具体来说到底是一个什么东西呢?字面意思,用来装东西的集装箱。装什么东西?除了应用程序本身之外,还包括这个应用要能正常运行所需的运行环境和库文件等外部依赖。我们想象一下现实世界中的集装箱。一辆汽车从码头上被装到集装箱里,然后被货船载到另一个码头里。这里的汽车就好比我们的应用,集装箱就是容器,汽车在不同的码头上装入集装箱就好比应用的部署。这就是slide里第一条,Convenient package to ship things的概念。Open specification:要注意,容器 != Docker。Docker只是容器技术的一种商业化实现方案。在2015年,由Google,Docker、CoreOS、IBM、微软、Redhat等厂商联合起来,成立了一个OCI(Open Container Initiative)组织,并于推出了第一个开放容器标准,旨在避免容器技术的碎片化。该标准主要分为运行时标准和容器镜像标准。Isolated:容器隔离。这个很好理解,容器里运行的应用彼此之间是隔离的,一个应用出故障不会影响到其他容器。可以独立分别进行水平扩展。Portable:既然容器封装了所有运行应用程序所必需的相关的细节,比如应用依赖以及操作系统,这就使得镜像从一个环境移植到另外一个环境更加灵活。比如,同一个镜像可以在Windows或Linux,开发、测试或生产环境中运行。基于容器的应用,既能运行在开发者的笔记本电脑上,也能运行在云服务提供商的数据中心上。真正做到一次构建,到处运行。LightWeight:轻量级。虚拟机和容器的目的类似,都致力于对应用程序及其关联性进行隔离,从而构建起一套能够不依赖于具体环境而运行的应用单元。虚拟机是在物理服务器的上层用软件来模拟特定的硬件系统。Hypervisor位于硬件和系统之间,是创建虚拟机必须的一个部分。虚拟机软件必须使用Hypervisor作为一个中间层,是虚拟机技术的核心,当宿主操作系统启动虚拟机时,会通过hypervisor给虚拟机分配内存,CPU,网络和磁盘等资源,并加载虚拟的操作系统,因而需要消耗宿主机大量的物理资源。一台宿主机上运行的多个容器化应用共享这台宿主机操作系统的内核,因而不需要虚拟机技术的hypervisor中间层,因而同虚拟机技术相比,更加轻量化,启动速度更快。那么容器和docker的关系又是怎样的?前面已经说到了,Docker只是基于开放容器标准的一种比较受欢迎的实现。Docker之于容器,相当于React,Angular和Vue之于UI开发框架。既然大多数时候我们在谈到容器时,都会不自觉地想到Docker,那么Docker到底是用什么实现的呢?著名的计算机科学家王垠,曾经在他的个人博客上撰文,声称Docker和Kubernetes并不是什么了不起的技术。从科学家的角度出发,这个论断不能算错误,因为Docker底层确实就是对Linux里很多原语做了很好的封装,所以从商业化的角度取得了成功。以下是一些Docker封装的Linux系统原语的一些例子。Jerry是SAP Docker和Kubernetes培训课程的讲师之一,在这个课程上,我们会对Docker如何凭借这些原语实现开放容器标准做深入的讨论。接下来,我们引入Kubernetes。为什么有了Docker后,还需要Kubernetes?我们知道从结果上看,Docker和虚拟机都可以做到让应用在隔离的环境下运行,区别在于Docker运行环境仍然能够和宿主机共享操作系统内核,而虚拟机则通过付出更多宿主机系统资源的代价,构造出一个完全虚拟的操作系统,让应用在里面运行。然而Docker容器和虚拟机还是有一些问题没有解决,就是容器在大型分布式集群上的部署,微服务应用中的容器管理和协同,自动地水平扩展,自动修复和弹性伸缩等等。这也是Kubernetes大显身手的地方。诞生于2015年7月的Kubernetes,是Google内部多年使用的容器集群管理系统Borg的开源版本。由于凝聚了Google在容器编排领域多年的深厚功力,发布之后很快就一飞冲天,如今已经成为事实上的容器集群管理领域的标准和霸主。Kubernetes源自古希腊语,意为“舵手”。有人调侃说,Google选择Kubernetes这个单词,暗示了自己想在容器编排管理这个领域里扮演舵手和领导者的角色。Kubernetes和Docker容器的关系?下面这张图片是SAP Kubernetes培训课程slide里的一张,用来说明Kubernetes和docker容器的关系,我觉得很形象。运行了各种微服务应用的容器就好比图中使用各种乐器演奏的音乐家,而站在中间的指挥家,和使用乐器演奏的音乐家站立的台阶,就相当于Kubernetes。如果更准确的说,Kubernetes管理的不是容器,而是pod。Pod是一个或者多个容器组成的集合。至此,我们终于完成了了解Kyma必须的前置知识的介绍。什么是Kyma?去年6月份,SAP C/4HANA正式announce时,这张图在大家的朋友圈中都刷屏似的存在。大家可以看到,Slide里的描述,SAP云平台扩展工厂是一个基于云端原生微服务的通用创新和敏捷平台。那么云平台扩展工厂和括号里的Kyma关系又如何?二者的关系恰如Open UI5和Fiori的关系。Open UI5是SAP推出的一个开源UI开发框架和UI控件库,而Fiori是SAP 基于Open UI5这个技术框架开发出来的商业化产品(当然现在Fiori也代表SAP推荐的一种UI风格)。类似的,SAP Cloud Platform Extension Factory是SAP基于Kyma这个开源项目,再针对企业应用所必须满足的一些标准(比如SAP产品标准,区域特殊需求)而添加进额外的附加功能和实现的商用产品。Kyma对C/4HANA意味着什么?我们CX部门的CTO Moritz Zimmermann, 在他的linkedin上发表过一篇博客,里面也提到了Kyma:Kyma(SAP Cloud Platform Extension Factory)将来会成为SAP C/4HANA套件里所有基于微服务架构产品的统一扩展工具。Kyma是基于Kubernetes的,这也是我们之前花了很多时间进行Docker和Kubernetes介绍的原因。那么Kyma的工作原理是什么?简单的说就是一个观察者-发布者模式。1. 通过Application Connector,可以使Kyma同SAP C/4HANA的产品建立连接,然后进行事件注册。2. 事件注册好之后,使用微服务架构实现事件的监听者(消费者)。这也是Kyma官网里提到的"开发者可以使用任何技术栈进行扩展开发“的含义。举个例子,我们在SAP Commerce Cloud里创建一个订单后,客户提出了基于该企业流程的一些特殊校验逻辑。Commerce Cloud发布一个"Order Create"的事件,事件payload包含创建订单的字段。我们开发并部署在Kyma上的微服务监听这个事件,微服务内部实现可以采取任何技术栈,Commerce Cloud通过HTTP调用包含了企业自定义订单校验逻辑的微服务,根据其返回的校验结果进行后续处理。我们来看一个具体的demo,看看SAP Commerce Cloud里订单编排功能是如何用Kyma去增强的。下图蓝色流程是我们通过Kyma对Commerce Cloud的标准流程进行的增强,主要是在下单过程中增加了一些Validation校验。我们登录commerce的back office页面,定义一个新的action:然后进到Kyma的console页面:选择一个stage进去,点击Lambdas进入编辑页面:新建一个Lambda function,取名fraudcheck2:这个function自动创建的标签(Labels),Kubernetes老司机一定觉得很亲切。这些标签其实和大家现实工作中使用云笔记里的标签和图片管理软件里的标签作用相同,就是一种键值对(Key Value Pair), 可以允许用户把Kubernetes的对象能灵活的分组,并提供高效的检索。Function Trigger里可以指定这些Lambda函数在哪些事件触发后执行。选择第一步定义新的action后对应的event:Lambda函数具体的实现,做过nodejs开发的朋友们一定不会觉得陌生。首先第18行,19行从event这个输入参数对象里取得发生事件的订单Code,然后第26行消费OCC(Omni Commerce Channel)Restul API获得订单明细,从明细里获得订单的客户ID,再调用第30行的代码根据客户ID拿到客户明细,然后使用第37行和第40行的代码分别检查该客户的邮箱地址是否有效,以及该客户是否第一次下单。注意第43行和46行的代码我暂时注释掉,稍后才会启用。现在我们来测试一下。在Commerce里下一个单,记下订单ID。回到Commerce back office页面,查看刚才下的订单的Business Process:这里看到了刚才第一步新建的基于Kyma Action对应的流程日志记录:我们再去查看这个订单的Fraud检查记录:点这个Fraud Reports查看检查结果。这个标签从左到右依次排开的风格很像Fiori和ABAP Webdynpro。可以看见前文介绍的Email和是否是首单的检查结果。Email检查结果,客户的邮箱地址有效。现在再回到Kyma的Lambda函数编辑器里,将之前注释掉的从Marketing Cloud获取联系人地址的函数以及调用SAP云平台的Business Partner服务的函数重新启用:启用之后,保存,然后进入Service Catalog。这个组件也是Kubernetes提供的标准组件,Kyma基于它做了增强,能够将第三方的服务导入进来给Kyma的Lambda函数消费。接下来的步骤和我们在SAP云平台上消费一个服务类似,首先创建一个服务实例:然后再基于这个服务实例创建一个绑定,绑定类型设置成Function Binding,绑定的目标设置成之前编辑好的Lambda函数。再下一个单:这一次,这个第二次下的订单的Fraud检查报告,同第一个订单相比就多了两条记录:首先看第二条首单检查的记录,得分为0,和我们期望的结果一致。从Marketing Cloud的服务返回的检查结果:从SAP云平台的Business Partner服务返回的结果可以看出,下单的这个客户不存在一个对应的Business Partner。至此关于如何使用Kyma对SAP Commerce产品的订单编排做增强就简单介绍到这里,感谢阅读。要获取更多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

小技巧:浏览器里显示成星号的密码,忘记了该怎么办?

比如下图这种,记性不好,忘记了密码该怎么办?很简单,Chrome浏览器里按F12打开开发者工具,切换到Elements面板,点击下图Step1的图标,然后单击密码显示框,保持这个字段处于选中状态,然后切换到Console标签页,输入$0.value, 回车就能看到密码了。要获取更多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 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