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 Read

https://blogs.sap.com/2017/03/22/buffer-logic-in-one-order-header-extension-read/

2. Logic of FILL_OW function module in One Order

https://blogs.sap.com/2017/03/22/logic-of-fill_ow-function-module-in-one-order/

3. Logic of CHANGE_OW function module in One Order

https://blogs.sap.com/2017/03/23/logic-of-change_ow-function-module-in-one-order/

4. Logic of CREATE_OW function module in One Order

https://blogs.sap.com/2017/03/24/logic-of-create_ow-function-module-in-one-order/

5. Logic of SAVE_EC function module in One Order

https://blogs.sap.com/2017/03/23/logic-of-save_ec-function-module-in-one-order/

6. CHANGED_AT, HEAD_CHANGED_AT and CRM_CHANGED_AT in order header table

https://blogs.sap.com/2017/04/27/changed_at-head_changed_at-and-crm_changed_at-in-order-header-table/

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社区了,这里只简述一些核心概念。

为什么要改造?因为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/discussions/thread/3602400

从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两款产品中的订单模型设计有最基础的认识,感谢阅读。

相关阅读

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

SAP CRM系统订单模型的设计与实现的更多相关文章

  1. SAP CRM 用户界面对象类型和设计对象

    在CRM中的用户界面对象类型的帮助下,我们可以做这些工作: 进行不同的视图配置 创建动态导航 从设计层控制字段标签.值帮助 控制BOL对象的属性的可视性 从导航栏访问自定义组件 一个用户界面对象类型之 ...

  2. SAP CRM点了附件的超链接后报错的处理方式

    SAP CRM系统里,点击了附件的这些超链接后,如果是文本文件,会在浏览器里打开.如果是其他类型的文件,会弹出下载对话框. 然而最近我工作时遇到一个问题,点击超链接后,总是弹出Logon failed ...

  3. Java高级项目实战03:CRM系统数据库设计

    接上一篇:Java高级项目实战02:客户关系管理系统CRM系统模块分析与介绍 欢迎点击回顾,接下来我们说说 CRM系统数据库设计. 我们根据产品的原型搞以及UI组的设计稿, 接下来就要设计数据库, 一 ...

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

    尽管有一万个舍不得,2018年还是无可挽回地离我们远去了. 唯有SAP成都研究院的同事和我去年在网络上留下的这些痕迹,能证明2018年我们曾经很认真地去度过每一天: SAP成都研究院2018年总共87 ...

  5. 浅谈SAP CRM和Hybris Commerce里的价格架构折扣

    最近Jerry做了一个和价格折扣相关的原型项目,把学到的知识记录下来,以备将来查阅. 在这个原型项目里,我们用React-Native开发了一个移动应用,用户可以在手机上浏览SAP Hybris Co ...

  6. SAP CRM BOL编程基础,代码+详细注释

    网络上可以找到一些使用BOL查询.维护数据的DEMO,但几乎都是单纯的代码,缺乏说明,难以理解.本文除了代码外,还给出了详细的注释,有助于理解BOL编程中的一些基本概念. 这是一篇翻译的文章,你可能会 ...

  7. 如何在CRM系统中集成ActiveReports最终报表设计器

    有时候,将ActiveReports设计器集成到业务系统中,为用户提供一些自定义的数据表,用户不需要了解如何底层的逻辑关系和后台代码,只需要选择几张关联的数据表,我们会根据用户的选择生成可供用户直接使 ...

  8. SAP CRM 最新简介文字(2007年、中英文)

    以下内容是SAP CRM功能的精简描述,摘自SAP官方文档,附上中英文版本,可以对SAP CRM的主要功能有大致了解. 营销 - 使用营销资源管理.客户细分及列表管理.营销活动管理.线索管理.贸易促销 ...

  9. SAP CRM 高效调试方法

    调试,是程序开发中的基本技巧.快速定位错误消息在源代码中的位置,对发现和解决程序中的问题有着重要的意义.在SAP CRM中,错误消息通常在前台的Web Client页面中展示,应该怎样定位相关代码的位 ...

随机推荐

  1. 在ubuntu10.10下安装Google谷歌拼音输入法

    安装步骤如下:1.下载文件:sudo wget http://malu.googlecode.com/files/scim-googlepinyin.tar.gz(经测试,这个链接已经失效了,幸好有前 ...

  2. RequireJs使用快速入门

    前言:Requirejs作为一个ES5环境流行的模块加载器,在很多项目中使用它.而且这个开源库任然在更新,同类产品seajs已经不更新了. ES6之后引入import 或者使用Commonjs的方式引 ...

  3. ORM框架SQLAlchemy的使用

    ORM和SQLAlchemy简介 对象关系映射(Object Relational Mapping,简称ORM),简单的来说,ORM是将数据库中的表与面向对象语言中的类建立了一种对应的关系.然后我们操 ...

  4. android socket 通讯(客户端) 发送数据

    /** ClientSocket通讯类 **/  public class ClientSocket  {     /**服务器地址*/     private String serverUrl=&q ...

  5. .net core 填坑记之二目录问题(获取当前目录、创建目录)

    1.获取应用程序运行当前目录Directory.GetCurrentDirectory(). System.IO命名空间中存在Directory类,提供了获取应用程序运行当前目录的静态方法GetCur ...

  6. 樹莓派3B運行.Net Core2.1 Web 項目

    安裝.Net Core 運行時和SDK(非必選) 下載地址 安裝 # 安裝運行時 sudo apt-get -y update # Install the packages necessary for ...

  7. [模拟回调] demo1模拟用字符串调用js函数 demo2模拟springmvc controller回调页面js函数

    demo1. 模拟用字符串调用js 函数 function dataQuery() { var strFun = "testCallBack"; var strParam = &q ...

  8. svn 创建本地仓库

    1. svnadmin create ~/repository 2. svnserve -d -r ~/repository 3. svn checkout file://~/repository $ ...

  9. UNIX 5种I/O模型

    Unix 5 I/O模型 I/O操作分为两步: (1)先将数据从 存储介质 (磁盘或者网络等)拷贝到 内核缓冲区,此时称为数据准备好,可以被用户读取. (2)由用户应用程序拷贝内核缓冲区数据 到用户缓 ...

  10. csharp:.net 3.5 using System.Runtime.Serialization.Json read json

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...