我的BRF+自学教程(三):动态技术
开发者们可以在编程中使用各种动态技术,比如RTTS,比如通过动态的类创建和多态来实现功能的平滑扩展。BRF+开发中也存在一些动态手段。本文将介绍3种不同场景下的动态实践方式。其中第一种是纯配置的,第二和第三种是编程相关的。
本文链接:https://www.cnblogs.com/hhelibeb/p/9571707.html
我的BRF+教程系列:https://www.cnblogs.com/hhelibeb/tag/BRFplus/
1,动态表达式(Dynamic Expression)
动态表达式是一种特殊类型的表达式,它可以用来实现对其它表达式的动态调用。动态表达式的应用场景之一是,有很多个表达式可以供用户选择,这些表达式使用基本一样的上下文对象,你不希望为每个表达式创建一个函数(因为创建它们的过程太繁琐),而是希望在一个统一的入口函数去调用。
1)选项
- 被调用的表达式(Called Expression):选择一个表达式,将它分配给动态表达式。被分配的表达式会在运行期间被动态表达式调用。注意,虽然被称为被调用的表达式,但是它并不是被动态调用的表达式,它的返回结果才是被动态调用的表达式的ID。Called Expression可以处理动态表达式的上下文,结果中必须包含一个表达式的ID,该表达式的结果会被传回给动态表达式。
- 结果数据对象(Result Data Object:)结果数据对象可以使用任何种类的对象。然而,很重要的一点是确保第二个被调用的表达式的结果数据对象和动态表达式的结果数据对象是兼容的。
2)限制
动态表达式可以提供灵活性,但它也有缺陷,因为动态表达式类型的特质,使得某些大部分可以应用在其它BRF+表达式上的检查无法应用在动态表达式上面。所以这可能导致一些设计缺陷无法被检查出来,只有在运行期间才会暴露。此外,动态表达式是不支持代码生成模式的,只能使用解释模式,这使得它的性能不太好,在对时间要求高或数据负载量大的时候不建议使用它。
3)例子
实际操作部分比较简单,读完上面的文字之后应该可以很顺利地出来,这里就不再一图一图地贴了。可以参考官方文档。
2,动态创建决策表(Decision Table)
通过使用ABAP代码,可以动态地创建BRFplus中的decisiong table和function等对象。
(本节的内容基本来自于Create decision table & it’s entries dynamically in BRF + Workbench through API)
1)前提
要读懂本节,需要两方面的知识,
- 基本的ABAP面向对象知识。
- 基本的BRF+知识。
2)需求
通过一个简单的report程序来创建决策表和它的条目。
3)使用的接口
- IF_FDT_FACTORY
- IF_FDT_DECISION_TABLE
- IF_FDT_FUNCTION
4)创建应用
在工作台中创建一个应用,接下来将会在这个应用中动态地创建决策表。
5)复制代码
把以下代码粘贴到自定义程序中,代码的具体意义写在注释中,注意ID要替换成你自己创建的BRF+应用的ID
DATA: lo_factory TYPE REF TOif_fdt_factory,
lt_messageTYPE if_fdt_types=>t_message,
lv_messageTYPE string,
lv_booleanTYPEabap_bool,
lo_elementTYPE REF TOif_fdt_element,
lo_tableTYPE REF TOif_fdt_table,
lo_structureTYPE REF TOif_fdt_structure,
lv_element1_idTYPE if_fdt_types=>id,
lv_element2_idTYPE if_fdt_types=>id,
lv_element3_idTYPE if_fdt_types=>id,
lv_structure_idTYPE if_fdt_types=>id,
lo_constantTYPE REF TOif_fdt_constant,
ls_elementTYPE if_fdt_structure=>s_element,
lts_elementTYPE if_fdt_structure=>ts_element,
lv_stringTYPE string,
ls_rangeTYPE if_fdt_decision_table=>s_range,
ls_table_dataTYPE if_fdt_decision_table=>s_table_data,
lo_decision_tableTYPE REF TOif_fdt_decision_table,
lo_functionTYPE REF TOif_fdt_function,
lo_contextTYPE REF TOif_fdt_context,
lts_context_idTYPE if_fdt_types=>ts_object_id,
lts_table_dataTYPE if_fdt_decision_table=>ts_table_data,
lts_columnTYPE if_fdt_decision_table=>ts_column,
lv_actv_failedTYPEabap_bool,
lx_fdtTYPE REF TOcx_fdt,
lv_dt_idTYPE if_fdt_types=>id,
ls_columnLIKE LINE OFlts_column.FIELD-SYMBOLS: <ls_message> TYPE if_fdt_types=>s_message,<lv_value> TYPEany.*获取FDT工厂实例,使用上面创建的应用IDlo_factory= cl_fdt_factory=>if_fdt_factory~get_instance('005056A4CCA61ED8AA9AAF84A7712616' ).
*创建数据对象lo_element ?= lo_factory->get_data_object(
iv_data_object_type= if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'IV_VAR1').
lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(IMPORTINGet_message=lt_message
ev_activation_failed=lv_boolean ).IF lv_boolean EQabap_true.*如果激活失败,需要处理 lo_element->if_fdt_transaction~dequeue( ).ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ).*通常需要把ID单独存下来,以便后续操作lv_element1_id= lo_element->mv_id.
ls_element-position = 1.
ls_element-element_id =lv_element1_id.APPEND ls_element TOlts_element.ENDIF.INSERT lv_element1_id INTO TABLElts_context_id.*创建另一个元素 lo_element ?= lo_factory->get_data_object(
iv_data_object_type= if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'IV_VAR2').*设置元素类型(可以搜索if_fdt_constants=>gc_element_type_* 得到可用元素类型列表 lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(IMPORTINGet_message=lt_message
ev_activation_failed=lv_boolean ).IF lv_boolean EQabap_true. lo_element->if_fdt_transaction~dequeue( ).ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ). lv_element2_id= lo_element->mv_id.
ls_element-position = 2.
ls_element-element_id =lv_element2_id.APPEND ls_element TOlts_element.ENDIF.INSERT lv_element2_id INTO TABLElts_context_id.*创建结果数据元素 lo_element ?= lo_factory->get_data_object(
iv_data_object_type= if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'EV_RESULT').
lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(IMPORTINGet_message=lt_message
ev_activation_failed=lv_boolean ).IF lv_boolean EQabap_true. lo_element->if_fdt_transaction~dequeue( ).ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ). lv_element3_id= lo_element->mv_id.
ls_element-position = 3.
ls_element-element_id =lv_element3_id.APPEND ls_element TOlts_element.ENDIF.INSERT lv_element3_id INTO TABLElts_context_id.*填充第1列元素ls_column-col_no = 1.
ls_column-object_id =lv_element1_id.
ls_column-is_result =abap_false.INSERT ls_column INTO TABLElts_column.* 填充第2列元素
ls_column-col_no = 2.
ls_column-object_id =lv_element2_id.
ls_column-is_result =abap_false.
INSERT ls_column INTO TABLElts_column.
*填充结果列元素
ls_column-col_no = 3.
ls_column-object_id =lv_element3_id.
ls_column-is_result =abap_true.
INSERT ls_column INTO TABLElts_column.
*创建并设置决策表表达式
lo_decision_table ?= lo_factory->get_expression( iv_expression_type_id= if_fdt_constants=>gc_exty_decision_table ).
*对表达式加锁.
lo_decision_table->if_fdt_transaction~enqueue( abap_true ).
*设置表列
lo_decision_table->set_columns( its_column =lts_column ).
lo_decision_table->if_fdt_admin_data~set_name( 'DT_TEST' ). "user defined name. DT_TEST is the decision table Name
*使用工厂对象创建一个函数实例.
lo_function ?= lo_factory->get_function( ).
*对函数加锁.
lo_function->if_fdt_transaction~enqueue( ).
*设置函数上下文对象.
lo_function->set_context_data_objects( lts_context_id ).
lo_function->if_fdt_admin_data~set_name( 'FN_TEST' ). "自定义函数名
*设置函数根表达式.
lo_function->set_expression( lo_decision_table->mv_id ).
*设置单元格(1,1)的条件
ls_table_data-row_no = 1.
ls_table_data-col_no = 1.
ls_range-position = 1.
ls_range-sign = if_fdt_range=>gc_sign_include.
ls_range-option = if_fdt_range=>gc_option_equal.
CREATE DATA ls_range-r_low_value TYPE if_fdt_types=>element_text.
ASSIGN ls_range-r_low_value->* TO <lv_value>.<lv_value> = 'MOURI'.
INSERT ls_range INTO TABLE ls_table_data-ts_range.
INSERT ls_table_data INTO TABLElts_table_data.
CLEARls_table_data. .
*设置单元格(1,2)的条件
ls_table_data-row_no = 1.
ls_table_data-col_no = 2.
ls_range-position = 1.
ls_range-sign = if_fdt_range=>gc_sign_include.
ls_range-option = if_fdt_range=>gc_option_equal.
CREATE DATA ls_range-r_low_value TYPE if_fdt_types=>element_text.
ASSIGN ls_range-r_low_value->* TO <lv_value>.<lv_value> = 'TECH'.
INSERT ls_range INTO TABLE ls_table_data-ts_range.
INSERT ls_table_data INTO TABLElts_table_data.
CLEARls_table_data.**在单元格(1, 3)得到结果
ls_table_data-row_no = 1. ls_table_data-col_no = 3.
CREATE DATA ls_table_data-r_value TYPE if_fdt_types=>element_text.
ASSIGN ls_table_data-r_value->* TO <lv_value>.<lv_value> = 'MOURITECH'.
INSERT ls_table_data INTO TABLElts_table_data.
CLEARls_table_data.
*设置完全的表数据.
lo_decision_table->set_table_data( its_data =lts_table_data ).
*保存并激活.
lo_function->if_fdt_transaction~activate(
EXPORTING iv_deep =abap_true
IMPORTING et_message =lt_message
ev_activation_failed=lv_actv_failed ).
*如果成功,先保存对象。无论成功失败,释放全部锁
IF lv_actv_failed EQabap_true.
lo_function->if_fdt_transaction~dequeue( iv_deep =abap_true ).
WRITE : / 'Deep activation failed'.
LOOP AT lt_message ASSIGNING <ls_message>.
MESSAGE ID <ls_message>-msgid TYPE <ls_message>-msgty NUMBER <ls_message>-msgno
WITH <ls_message>-msgv1 <ls_message>-msgv2 <ls_message>-msgv3 <ls_message>-msgv4INTOlv_message.
WRITE: / 'Reason : -',lv_message.
ENDLOOP.
ELSE.
TRY.
lv_dt_id= lo_decision_table->mv_id.
lo_function->if_fdt_transaction~save( iv_deep =abap_true ).
WRITE : 'The ID of the decision table created is:',lv_dt_id. .
CATCH cx_fdt INTOlx_fdt.
WRITE : / 'Save failed with exception'.
LOOP AT lx_fdt->mt_message ASSIGNING <ls_message>.
WRITE :/ <ls_message>-text.
ENDLOOP.
ENDTRY.
lo_function->if_fdt_transaction~dequeue( iv_deep =abap_true ).
ENDIF.
ABAP 7.53 中的ABAP SQL(原Open SQL)新特性
S/4 HANA 1809 已经在上月发布,随之而来的是ABAP 7.53。
本文是更新文档中ABAP SQL的部分的翻译。
本次更新的内容较多,主要内容包括:Open SQL更名为ABAP SQL;新函数和表达式;限制移除;table buffer增强;更严格的语法检查规则等。
译者水平有限,如有错误之处,请评论指出。
本文链接:https://www.cnblogs.com/hhelibeb/p/9848373.html
1,Open SQL的新名字:ABAP SQL
Open SQL已经被更名为ABAP SQL。这个重命名反映出ABAP SQL的某些部分目前只支持特定的数据库平台(SAP HANA数据库),已经不再是全平台独立的了。
2,层次函数
层次函数(Hierarchy functions)是可以在查询中被指定为数据源的表函数(table function)。
3,辅助连接
在一个以SAP HANA为主数据库的ABAP应用服务器上,表DBCON里的辅助连接也应该是一个SAP HANA数据库。除了CONNECTION附加项以外,它也对ABAP SQL和NATIVE SQL生效。(ADBC和EXCE SQL)。
不再需要使用Database Shared Libraries (DBSL),而应使用SAP HANA Smart Data Access (SDA)。在SDA中,辅助数据库使用特殊限定名或使用虚拟表从SAP HANA数据库中寻址。如果将SAP HANA数据库是ABAP服务器主数据库,ABAP程序可以通过标准连接使用这些名字。只能通过AMDP或者Native SQL来使用这一功能。
4,关系表达式 IS INITIAL
可以在SQL条件中使用表达式 IS [NOT] INITIAL 来比较运算数和它们的类型初始值。
如果使用了该表达式,语法检查会以7.53版本的严格模式运行。
(译注:从文档来看,7.53版本的严格模式规则和7.52版本是相同的。)
5,日期/时间函数
ABAP SQL现增加了对以下日期/时间函数的支持:
- 时间函数
- TIMS_IS_VALID
- 时间戳函数
- TSTMP_IS_VALID
- TSTMP_CURRENT_UTCTIMESTAMP
- TSTMP_SECONDS_BETWEEN
- TSTMP_ADD_SECONDS
- 日期/时间转换
- TSTMP_TO_DATS
- TSTMP_TO_TIMS
- TSTMP_TO_DST
- 时区函数
- ABAP_USER_TIMEZONE
- ABAP_USER_TIMEZONE
如果使用了这些函数,语法检查会以7.53版本的严格模式运行。
6,发布公用表表达式的Associations
可以通过公用表表达式(common table expression,以下简称CTE)访问CDS视图,现在可以使用语句WITH的WITH ASSOCIATIONS附加项来发布这些视图的association,以便在当前WITH语句的路径表达式中使用。附加项REDIRECT TO也可以用于替换前CTE或当前CTE发布的association的目标数据源。
如果使用了该附加项,语法检查会以7.53版本的严格模式运行。
7,SELECT列表中的数字
此前,在SELECT查询中只能使用INT4类型范围内的值。现在,可以使用长度为31的数字,当其不在INT4类型范围内时,会被解释为DEC类型。
8,CAST增强
现在可以通过CAST表达式把INT1, INT2, INT3, INT4和INT8转换为DEC了。
9,INSERT语句子查询中的Client操作
现在,INSERT语句的附加项USING CLIENT可以在子查询中指定了。这意味着在插入操作中指定的目标表的client可以不同于子查询数据源的client。
如果没有在子查询中指定USING CLIENT,自动client操作会应用当前的client ID。在7.53之前,使用USING CLIENT指定的client ID也会在子查询中使用。
现在子查询的FROM子句可以访问使用INSERT语句填充的数据库表或经典视图,这意味着可以从一个client复制数据到另一个client。
使用这一特性时,语法检查会以7.53版本的严格模式运行。
10,以子查询为数据源的MODIFY
在ABAP SQL的写语句MODIFY里,可以在FROM关键字后面使用一个加上括号的SELECT subquery_clauses来实现以子查询作为数据源。子查询的数据结果集的行,会直接在数据库中插入或更新到目标表里。不再需要把数据从数据库传输到ABAP应用服务器了。
使用这一特性时,语法检查会以7.53版本的严格模式运行。
11,USING CLIENT和会话变量client
如果在一个ABAP SQL读语句中,存在对一个特定于客户端的CDS视图的多查询,并且该CDS视图中使用了annotation:@ClientHandling.algorithm:#SESSION_VARIABLE的话,多个查询中的会话变量client(相当于SAP HANA数据库中的ABAP特定会话变量CDS_CLIENT)必须设为同一值。如果为其中某项查询设定了不同的值,则会发生运行时错误SAPSQL_DIFFERENT_CLIENT_VALUES。这种情况会在使用了WITH语句或者UNION语句时发生。
12,表缓存中的null值
现在表缓存支持真null值了,null值不再被转换为类型初始值。在访问缓存时,会产生和直接访问数据库时一样的结果。不再存在相应的限制。这会影响到以下方面:
- 对于包含null值的关系表达式,现在在缓存中进行比较的时候,结果也是unknown了(除非表达式是IS [NOT] INITIAL)。
- IS [NOT] NULL不再绕过缓存。
- 访问被缓存的CDS视图。当缓存被访问时,会产生和直接访问数据库相同的结果。null值通常由outer join或某些表达式如case表达式产生。已经不再存在只有不产生null值的CDS视图才能被缓存的限制。
13,限制移除
- 对于某些SQL表达式和函数,ABAP SQL的读语句不再绕过缓存。
- 在不需要识别单行或者generic range的条件里,当某列指定在比较或者BETWEEN的右侧时,ABAP SQL读语句不再绕过缓存。前提是两个运算数都是数字类型的、并且不是DF16_DEC类型或者DF34_DEC,或者都是字符类型的,或者都是都是RAW类型、且具有相同长度。
14,弱检查
在ABAP SQL语句里使用了不被全部数据库平台支持的特性时,不会再产生语法检查警告,而是产生扩展程序检查警告。
15,新检查
如果以内表作为SELECT语句的数据源时,内表需要被传递给数据库表,会产生一个语法警告。可以使用pragma ##itab_db_select来隐藏这个语法检查警告。
16,程序调用中的替换服务
类CL_OSQL_REPLACE中的方法ACTIVATE_REPLACEMENT有了新参数FLG_SURVIVE_SUBMIT,允许在被调用的程序中进行重定向。
17,GROUP BY附加项GROUPING SETS
在一个SELECT语句中,可以使用GROUP BY附加项GROUPING SETS了。附加项GROUPING SETS可以在一个SELECT语句下进行多个分组聚合。也可以在一个语句中通过对相同的SELECT使用不同的GROUP BY子句分组、并且使用UNION来实现相同的功能。后者易出错并且对数据库来说更难优化。相比之下,GROUPING SETS附加项也使得解释和维护SELECT语句变得更简单。
18,聚合函数GROUPING
现在可以在SELECT语句中使用GROUPING函数。带有聚合函数GROUPING的聚合表达式在GROUP BY子句中担任分组集GROUPING SETS的分组函数。分组函数GROUPING可以区分出在结果集中的指定的列是否被聚合。只能在使用了包含GROUPING SETS附加项的GROUP BY子句的情况下使用该函数。
19,语法规则的更严格检查
过去在语法检查的严格模式的某些检查规则,现在在非严格模式下也会有效。在非严格模式下,违反这些规则会产生语法检查警告,在多数情况下,会导致程序运行期间产生运行时错误。
- 在访问视图时,键字段必须位于开始处。
- 在访问关联了CDS role的CDS entity时,不能使用附加项USING CLIENT和CLIENT SPECIFIED。
- 即使在使用路径表达式时,附加项CLIENT SPECIFIED也只能用于特定于客户端的数据源。
- 指定列时,对于包含include结构的数据库表,必须使用组件的实际名称,而不是ABAP Dictionary中定义的任何组的名称。
- 使用关键字AS定义的SELECT列表的别名最多可包含30个字符。ORDER BY后也不允许使用超过30个字符的备用列名。
- LCHR和LRAW类型的列只有在与相应长度字段一起读取时才能在查询中读取。
- 对于SELECT中的FOR ALL ENTRIES:
- 当数据源的列与内表列之间进行比较且它们的类型为p时,小数位必须匹配。
- 在ORDER BY之后使用PRIMARY KEY指定的主键的所有列也必须出现在SELECT列表中。
- 只能为具有基本行类型的内表指定伪组件table_line。
- 对于聚合函数之外、在HAVING后指定的列,必须使用GROUP BY分组。这也适用于在使用了HAVING子句的时候直接在SELECT列表中指定、但没有在GROUP BY后指定的列。
- 如果SELECT列表指定为*,HAVING子句只能同GROUP BY子句一起使用。
- 如果ORDER BY后使用了别名,这个名字必须是唯一的,也不可以和没有别名的列的名字相同。
- 在into后指定的工作区wa的字段少于SELECT列表中的显式字段。
- 在SELECT列表中显式指定的字段无法被赋给into子句中相应的结构工作区wa里的字段,或者无法赋给由括号包围、逗号分隔的数据对象。
- 在LIKE的右侧,不能指定长度是左侧字段2倍以上的字符文本或常量。
- 使用UPDATE FROM或MODIFY FROM访问所有字段都是键字段的投影视图。
- 使用INSERT FROM, UPDATE FROM,或者MODIFY FROM创建写入流时指定于通用的引用(A reference that is too general)。
- 在语句UPDATE中,列只能出现在单个更新表达式(update expression)的左端。
SAP CRM Installed Bases(IBase)简介
SAP CRM使用Installed Base(以下简称IBase)来组织服务相关对象并进行管理。因为我在最近的工作中经常接触这个概念,所以学习了一点相关文档。下面是文档的翻译。
本文链接:https://www.cnblogs.com/hhelibeb/p/9952344.html
英文原文:Installed Bases
定义
IBase是包含IBase组件的多级结构。IBase用于管理已在客户位置安装(或将要安装)的对象,例如设备、机器或软件。IBase描述了这些对象的层级结构和它们的各个组件,并且可以用作服务的参考基础。
应用
IBase适合存储你的客户结构和安装在客户位置的服务相关的对象。
可以参考IBase或IBase组件来确定服务合同和创建服务订单。
交互中心代理(Interaction center agents,客服)可以在联系客户时通过合作伙伴、地址、对象数据或IBase号码来搜索和显示IBase组件。交互中心内可以列出IBase的列表,其中的IBase组件可以作为服务业务的参考对象被复制。
在前往客户现场前、或在现场时,现场服务代表或服务员工可以通过移动设备(比如笔记本电脑)显示、变更IBase数据,以及创建新的IBase。
通过E-Service,客户的员工可以创建IBase或者访问已经存在的IBase。他们也可以为这些IBase创建投诉或者服务请求。
有两个基本的创建和维护IBase的方式(二者可以结合使用)
- 一个IBase对应多个对象
将一个客户的全部对象分组到一个IBase中。这个选项在单个对象的子结构的重要性不大的时候特别有用。 - 一个IBase对应一个对象
为每个和服务有关的对象创建一个IBase(也就是为每个设备、每个机器、全部软件等等)。这个选项在单个对象的子结构比较重要的时候特必有用,比如,大机器的服务备件订单。
结构
IBase显示为树形结构。
IBase由以下部分组成:
- IBase本身是一个分组单元,你将所有的部分(组件)分组到了一个结构中。
- IBase组件(见Installed Base Components)是IBase内的部分。
注意:名词IBase指的是整个IBase和全部被分配的组件。一个IBase本身也可以是其它IBase的组件。
当你变更结构和组件的时候,有效性间隔会被确定,因此你可以追溯之前的状态。(译注:没看懂什么意思,可能理解不对。原文:When you make changes to the structure and components, validity intervals are determined, so that you can retrace previous statuses.)
系统会为IBase分配ID。你也可以输入一个外部ID或者描述。
例子
IBase可以是一个厨房电器、建筑物里的一台电梯、或者一家公司的建筑物里的全部电梯。
IBase也可以包含复杂对象,比如一架飞机和所有服务相关的部分,或者一架尚未建造的、但是相关部分需要从计划和建造开始的阶段受到管理的飞机。
飞机的IBase也可以包含两翼,它应该在制造后与高层IBase(飞机)建立继承关系。
下图展示了一个IBase的例子,代表一个IT系统,并包含解释。
图中有一个为IT系统创建的IBase。IBase有地址和合作伙伴数据。在IBase的第一个子层级,以下文本组件已经创建:
- Room A01
该组件有以下低级别文本组件:
- Desk 1
这个组件下面是一个产品组件,代表一台PC。 - Desk 2
这个组件下面是一个产品组件,代表一台PC。 - Desk 3
这个组件下面是一个产品组件,代表一台PC。
- Desk 1
- Room A02
该组件有一个低级别文本组件Desk 1。Desk 1下面有以下产品组件被创建:
- 一台PC。
- 一台扫描仪。
- 一台彩色打印机。
对象组件“激光单元A4587-AD78”被分配给了该组件。
- Room B01
该组件有以下低级别组件:
- 一台复印机的对象组件。
- 一台打印服务器的IBase。
参考阅读:What is IBase?
SAP Change Request Management (ChaRM)基础教程
本文介绍了SAP Solution Manager中的变更请求管理工具(Change Request Management,以下简称ChaRM)。
最近打算写个上线前请求号检查工具,为此需要了解相关工具的工作方式。本文中的部分内容似乎前后有所出入,请自行判断。如有翻译错误请在评论指出。
本文链接:https://www.cnblogs.com/hhelibeb/p/9929331.html
英文原文:Basic Procedure for Change Management (ChaRM)
CHaRM是什么?
- SAP ChaRM是一个包含在SAP Solution Manager内的工具,它可以实现对变更的从设计到测试到传输生产的过程管理。它允许你在整个业务解决方案中跟踪变更请求(CR)和传输请求(TR)。
- SAP ChaRM使用基于工作流的审批来管理TR和解决方案蓝图中的功能变更。
- 在ChaRM的project的帮助下,我们可以扩展TMS的功能,确保所有传输请求一起移动QA,将集成/回归测试作为整体进行,并将它们共同导入到生产系统。
- 在某些方面不再需要电子表格(Excel),因为SAP Solution Manager Project会持续跟踪项目与传输请求的关联关系、以及传输请求的导入顺序。
前提
- 用合适的路径正确配置系统。
- Solution Manager和卫星系统间的RFC连接正常。
- 配置STMS。
- 定义系统间的传输路径。
- 激活TMS中的扩展传输控制。
- 取消激活质量保证审批程序(quality assurance approval procedure)、激活单一传输策略。
处理步骤
ChaRM涉及到项目中的以下机构,
- 请求者:认为配置变更和ABAP变更导致了错误的人。请求者会在Solution Manage中提出变更请求。
- 变更经理:负责决定和审批变更请求的人(原文"advisory board")。
- 开发者:根据每个变更请求来进行更改的人。他们可能是functional consultant和technical consultant。
- 测试者:测试团队(包含functional consultant和用户)。
- IT运维:Basis等。
步骤流程图如下,(注:图和下面的步骤描述似乎不一致,原图如此。个人认为下面的步骤描述更准确)
在Solution Manager CRM中的实际步骤如下,
我们在事务代码“SM_CRM”中得到了变更请求,需要在SAP中进行配置变更。这是我们从服务台得到的配置方面的一些变更事件(Incident)。
创建事件的时候,我们需要把状态变更为“Suspended”状态,或者根据配置设置为其它状态
获取suspended状态的问题清单,并且为变更创建请求。
前往Solution Manager的事务代码“SM_CRM”。点击下图中的Request for Change来创建CR。
当你点击"Request for Change"后,系统会展示如下界面,
在该界面中,输入
- Description:细节描述。
- Sold to Party:选择提出变更的人的名字。
- Requester:会自动出现。是创建CR的用户名。
- Approval Procedure:选择Change Request Approval Procedure。
- Priority:选择CR优先级。
- Project:输入项目名。
系统状态是自动设定的,我们不能手工修改。
在下方输入细节描述。也可以上传文档。
输入请求的修改范围,
这里我们选择600 client,配置条目是"7100000058"。
保存。
现在请求者(Requester)应前往CR,使用工具栏的action按钮,设置状态为"Validation"。
保存,系统会显示单据状态为Validation。
请求者完成了确认,现在他可以把请求提交审批了。在Action处选择"Release for Approval"。
保存后,状态会变为"To be approved",如下图。
变更经理(Change Manager)开始工作,他会检查请求,并按下面的操作审批。
变更经理会把状态设置为"Approved"或其它状态。
假设他选择了"Approved"并保存了请求。
现在请求者会看到审批过的请求。请求应该被发布为开发中状态,
保存,状态显示审批后的请求已经进入了处理中的状态。如果CR和ABAP开发相关,那么请求附件中需要包含FS文件。
可以看到状态是"Being Implemented".
当我们保存状态为"Being Implemented"的CR的时候,系统会生成一个change note号码,
前往变更对象,内容如下。当前的处理着可以填写下面的内容,
Developer:处理者将会填写这项,指定将会进行开发或配置的人。
Tester:将会在配置变更/开发完成后测试的人。
IT Operator:业务端的测试者或者是负责将请求传输到测试和生产系统的人。(注:原文如此)
变更问题的状态为"In Development",并保存。
在这步之后,请求会被传输到测试系统,相关人员进行测试。
优势
- SAP ChaRM允许组织有效地控制和管理SAP系统中的更改。
- 通过实现对某些点的强制控制和文档化的步骤,它保可以证对SAP系统的任何更改都遵循标准流程和程序。
- 提供跟踪和审计变更的能力。
- 通过配置CTS +,ChaRM可扩展到项目中的所有ABAP和非ABAP SAP环境。
- ChaRM不仅仅是对传输的技术管理工具,它还是一个功能强大的项目变更跟踪系统。它提供以下功能:
- 提供对需求和变更请求的可追溯性。
- 通过利用工作流来表示针对每个变更请求采取的行动。
- 报告和跟踪各个变更请求的状态和整个项目的状态。
- 为变更管理审计提供审批跟踪。
- 基于项目阶段,为传输请求提供防护。比如:如果某项目正处于测试阶段,尝试传输相关内容至生产的话,会遇到错误消息:“你不能在当前传输某项目的任何请求”。
SAP CRM 集类型(Set Type)与产品层次(Product Hierarchy)
本文是产品与对象相关的部分SAP文档的翻译,不包含配置部分。
本文链接:https://www.cnblogs.com/hhelibeb/p/10112723.html
1,对象(Objects)
对象是全局唯一的有形或无形对象,公司销售它或为它提供服务。对象通常是继承自产品的特定单一单元。然而,不像产品,对象是唯一的。这意味着虽然可能有相似的对象,但至少有一个描述对象的属性是不同的。这通常是它的标识符。比如说,车子会有自己的号码牌。
对象构成的唯一实体是公司和相关方间业务的中心。例如,一家电力供应商,可以使用对象描述他们输电的位置,比如“建筑”或“住房”。
对象被集成在产品主数据中,提供给你用于在业务处理中创建、跟踪所需信息的工具。产品主数据提供了检索对象相关信息的中心源。
对象数据包含了特定业务处理需要的信息(例如客户调查,销售订单,服务处理,合同),以及其它在本质上描述或分类对象的基本数据。比如:
- 描述性数据,比如尺寸和数量
- 具备控制功能的数据,比如决定销售订单中的每个项目分类的项目分类组。
这一信息存储在单独的产品主数据记录中。相关数据集合在一个单一的数据库对象中,这样可以避免存储冗余数据。
以下是对象所具备的特点,
产品类型(Product Types)
产品类型描述对象的基本特性,它也决定可以分配到对象的分类,从而决定对象的特性和它被使用的方式。(Only the product type Materialcan be used for objects.)。产品类型包含以下几种,
物料
服务
保修
金融
金融服务
知识产权(IP)
对象族(Object Family)
每个对象都属于一个对象族。对象族是基于对象属性的分组。创建对象时,必须为其分配对象族。
属性和集类型(Attributes and Set Types)
属性用于描述被划分为相同的集类型的对象。集类型的使用提供了在系统中为对象详细建模的能力。
分类和层次(Categories and Hierarchies)
分类和层次用于实现结构化,并且允许你将对象按照不同的条件分组。分类定义了允许被分配给对象的集类型和关系类型,从而允许你通过分配分类来将对象的信息按需要结构化。
关系(Relationships)
可以在对象间、产品间和产品与对象间创建关系,来表示特定的产品信息。例如组件,计数器,保修,资质要求等。
参考产品(Reference Products)
可以参考参考产品的技术和业务数据。
备选ID(Alternative IDs)
可以在产品主数据中定义备选ID,并且在业务处理中使用它们而不是对象ID。备选ID允许你在业务处理过程中使用满足行业标准的标识符,比如车辆识别号(VIN),序列号,ISBN。
例子:
2,集类型和属性
属性用于描述产品,集类型是产品的组。它们作为数据库表存储在系统中。
注意:在本节中,“产品”既指产品,也指对象。
集类型允许将数据字段组分配给产品,通过这样的方式可以为产品在系统中详细建模。
集类型和属性需要和产品层次、产品分类同时使用。这些元素的结合使相关的集类型可以在产品页被使用,从而描述产品。
结构
集类型被分配给分类,而不是直接分配给产品。通过将集类型分配给分类,相应地把分类分配给产品,你可以按需要提供描述产品的数据。
机制如下,
标准集类型
集类型可以是为了满足专门需求的自定义集类型,也可以是SAP标准的集类型。SAP提供了以下标准集类型,
通用集类型,
Technical Name
Description
COMM_PR_SHTEXT
COMM_PR_UNIT
COMM_PR_LGTEXT, COMM_PR_LGTEXT1, COMM_PR_LGTEXT2
CRMM_PR_SALESA
CRMM_PR_SALESG
CRMM_PR_TAX
物料集类型,
Technical Name
Description
COMM_PR_MAT
COMM_PR_GTIN
CRM_PR_RESIDVL
服务集类型
Technical Name
Description
CRMM_PR_BTR
CRMM_PR_SRVDUR
CRMM_PR_SRVRR
CRMM_PR_SRVENT
SERVICEPLAN
CRM_SERIALNUM
保修集类型
CRMM_PRWTY
CRMM_PRWTY_CAT
CRMM_PRWTY_SRV
CRMM_PRWTY_CNT
其它产品类型的集类型
Product Type
Set Types
Financing
Financial Service
Intellectual Property Management
3,产品层次
产品层次提供了一种结构化的机制,可以用于在产品主数据内建模。
注意:在本节中,“产品”既指产品,也指对象。
产品层次包含用于根据不同条件将产品分组的分类。层次的目的取决于你的公司的需求和业务标准。
层次可以是多级的,用来实现控制和信息方面的功能。
结构
层次内的分类是分层排列的。所有低层分类继承高层分类的产品类型和集类型。可以为低层分类分配附加的集类型。
例子如下(注意下面的集类型不是标准的,只是个自定义的例子):
如果一个产品类型被分配到分类,只有这个产品类型的产品可以被分配给分类。分配产品类型给分类使得可以将集类型分配给分类。集类型可以在产品或对象页面作为assignment block出现。
为了防止一个集类型被多次基于分类分配给同一个产品,在设定分类和层次时需要按以下原则进行:
- 一个集类型可以在同一个层次中被分配给多个分类,但是每个产品类型只能有一个层次。因此即使两个分类在不同的层次中、但是有相同的产品类型,也是无法将同时集类型分配给两个分类的。
- 一个产品可以被分配给多个分类,只要分类属于不同的层次。因此产品在各个层次中都只能分配给一个分类。
相关链接:SAP Document
- 一个IBase对应多个对象