二次开发-数据环境-增加状态及状态变迁
本帖最后由 adminlily 于 2020-12-15 16:42 编辑等待第3方的工单先决条件:您必须熟悉教程中使用的语法 并且已经创建了一个扩展.
学习:将状态添加到生命周期和计数中花费的时间
水平:[ ttps://www.itophub.io/wiki/page?id=level&dataflt%5B0%5D=level_%3DAdvanced]高级
域:[ ttps://www.itophub.io/wiki/page?id=domains&dataflt%5B0%5D=domains_%3DXML]XML, [ ttps://www.itophub.io/wiki/page?id=domains&dataflt%5B0%5D=domains_%3DStopwatch]stopwatch, [ ttps://www.itophub.io/wiki/page?id=domains&dataflt%5B0%5D=domains_%3DAutomation]antomation, [ ttps://www.itophub.io/wiki/page?id=domains&dataflt%5B0%5D=domains_%3DLifecycle]Lifecycle
最低版本:2.3.0
在此教程中,我们要标识支持团队正在等待第三方提供者信息操作的工单,如果没有该工单,则无法在工单上工作。为了实现这一目标,我们将:
[*]向UserRequest添加新状态,表明我们正在等待第三方提供者
[*]添加新的激励,以将用户请求移动到该新状态
[*]添加两个过渡,以允许将UserRequest移入和移出该新状态
在第二步中,我们要跟踪每个工单上等待提供者花费的时间。这要求:
[*]当工单处于“ pending_提供者”状态时,将UserRequest类上的秒表属性添加到计数。
[*]添加一个子项字段以显示等待提供者所花费的时间。
[*]仅在UserRequest的某些状态下显示等待第三方提供者花费的总时间
声明一个新状态
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=0]itop_design / classes / class@UserRequest / fields
<!-- Add a new state value to the existing status -->
<field id="status" _delta="must_exist"> <values>
<value id="pending_provider" _delta=define">pending_provider</value>
</values>
</field>
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=1]itop_design / dictionaries / dictionary@EN US
<!-- Give a label to the new state -->
<entry id="Class:UserRequest/Attribute:status/Value:pending_provider" _delta="define">
<!]>
</entry>
[*]请注意枚举价值的字典代码逻辑:Class:<class_name>/Attribute:
<attribute_code>/Value:<value_code>
添加刺激
该刺激与按钮和“其他操作活动”菜单相对应,当功能成为可能时,将在UserRequest的详细信息上提出该菜单。
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=2]itop_design / classes / class@UserRequest / lifecycle
<stimuli>
<!-- Add a new stimulus to switch to pending_provider state -->
<stimulus id="ev_pending_provider" xsi:type="StimulusUserAction" _delta="define"/>
</stimuli>
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=3]itop_design / dictionaries / dictionary@EN US / entries
<entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
<!]>
</entry>
[*]注意刺激的字典代码逻辑:Class:UserRequest/Stimulus:stimulus_id
[*]使用该刺激,刺激的标签将应用于所有过渡。
[*]通常,给定的刺激总是会停留在相同的状态。
[*]刺激声明没有指定如何使用,它可以用于任何状态之间的任何转换。
如果您需要为两个过渡使用不同的标签,请创建两个不同的刺激
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-menu.png
添加状态和过渡
转换的定义是:
[*]起始状态
[*]刺激,它会触发转换,并在启动状态下建议作为可能的功能
[*]结束状态,即对象在转换之后的结果状态
在这里,我们要提出两个可能的过渡:
[*]使用新创建的刺激“ ev_pending_provider”,将一个转换从“已分配”状态更改为“ pending_provider”状态。支持团队等待第三方提供者采取行动并做出响应时,将使用它。
[*]一个转换使用经典的“ ev_assign”刺激从“ pending_provider”返回到“分配”。提供者已完成操作并且支持团队可以与提供者解决一起使用时,将使用它。
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=4]itop_design / classes / class@UserRequest / lifecycle
<states>
<!-- This level define the state we are in -->
<state id="assigned" _delta="must_exist">
<transitions>
<!-- this define an available transition from the above state -->
<transition id="ev_pending_provider" _delta="define">
<!-- This define the stimulus which trigger the transition -->
<!-- on a given state there can only be one transition triggered by a
given stimulus -->
<stimulus>ev_pending_provider</stimulus>
<!-- This define on which state the UserRequest will end-up -->
<target>pending_provider</target>
<actions/>
</transition>
</transitions>
</state>
<!-- From the new state -->
<state id="pending_provider" _delta="define">
<flags /> <!-- it's a mandatory tag, even if empty -->
<transitions>
<!-- we want to assign the ticket back to the support team -->
<transition id="ev_assign">
<stimulus>ev_assign</stimulus>
<target>assigned</target>
<actions/>
</transition>
</transitions>
<!-- The fields are the same as in "assigned" state -->
<inherit_flags_from>assigned</inherit_flags_from>
</state>
</states>
定义新状态时,无需为每个字段重新定义,如果该字段在此状态下应为只读,隐藏或强制性的。您可以说它继承自另一个状态,并在<flags>标签下描述了差异。例如,请参见此教程:强制生命周期强制字段
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-transition.png
计数等待第三方的时间
在这个补充用例中,我们要跟踪每个工单上等待提供者花费的时间。为此,我们将
[*]当工单处于“ pending_provider”状态时,将UserRequest类上的秒表属性添加到计数。
[*]添加一个子项字段以显示等待提供者所花费的时间。
[*]仅在UserRequest的某些状态下显示等待第三方提供者花费的总时间
添加秒表
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=5]itop_design / classes / class@UserRequest / fields
<!-- Add a stopwatch to count the timespent in this state -->
<field id="providerstopwatch" xsi:type="AttributeStopWatch" _delta="define">
<states>
<!-- here are the states during which the stopwatch is counting time -->
<state id="pending_provider">pending_provider</state>
</states>
<working_time/>
<thresholds/>
<always_load_in_tables>true</always_load_in_tables>
</field>
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=6]itop_design[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=6]/ dictionaries / dictionary@EN US / entries
<entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
<!]>
</entry>
[*]这是秒表的最简单用法,只计算在特定状态下花费的时间
追踪花费的时间
必须执行此步骤,才能通过OQL在表单和查询中显示此信息。
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=7]itop_design / classes / class@UserRequest / fields
<!-- Declaring this stopwatch sub-item is required to display or query it -->
<field id="pending_provider_delay" xsi:type="AttributeSubItem" _delta="define"> <target_attcode>providerstopwatch</target_attcode>
<!-- Possible item_code: timespent, started, laststart, stopped-->
<item_code>timespent</item_code>
</field>
</fields>
您还可以声明其他子项目。
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=8]itop_design / dictionaries / dictionary@EN US / entries
<entry id="Class:UserRequest/Attribute:pending_provider_delay" _delta="define">
<!]>
</entry>
显示秒表
在此示例中,我们将自行显示秒表。此字段非常特殊,因为它是一个复合字段,它包含所有子信息,这些子信息都已显示。我们已决定始终显示秒表,而不管它是否正在运行。您将看到显示的数据在某些状态下将不可用。
假设您已经声明了子项目,那么子项目也可以独立显示,就像我们为子项目花费的时间所做的一样。因此,我们还将显示花费的时间。
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=9]itop_design / classes / class@UserRequest
<!-- Display the 2 new fields in the details of the UserRequest -->
<presentation>
<details _delta="must_exist">
<items>
<!-- First column of the UserRequest display -->
<item id="col:col1">
<items>
<item id="fieldset:Ticket:moreinfo">
<items>
<!-- Add the provider timespent delay -->
<item id="pending_provider_delay" _delta="define">
<rank>80</rank>
</item>
<!-- This displays a stopwatch (including some sub-items) -->
<!-- This will help you to understand how a stopwatch behave -->
<item id="providerstopwatch" _delta="define">
<rank>90</rank>
</item>
</items>
<rank>20</rank>
</item>
</items>
</item>
</items>
</details>
</presentation>
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-new.png
显示花费的时间
由于仅在秒表停止时才计算花费的时间-因此,当UserRequest退出“ pending_provider”状态时-
[*]它不应以“ pending_provider”状态显示,因为它没有提供准确的信息
[*]我们决定不将其显示为“新”状态,因为它无用且为空
[*]我们决定在工单是被解决或已关闭时以只读方式显示它,因为用户不应修改它。
我们在演示文稿中定义了该字段需要显示的位置,现在我们可以通过为每个状态定义该字段是隐藏还是只读来调整何时应该可用。
[*]当我们将字段定义为在new状态下隐藏时,因为状态链接在标准数据模型中,因此这会传播到以下所有状态。
[*]当我们在状态被解决中将其定义为只读时,它将覆盖隐藏标志
[*]当已关闭更改为被解决状态时,它仍然可见
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=10]itop_design / classes / class@UserRequest
<lifecycle>
<states>
<state id="new" _delta="must_exist">
<flags>
<!-- Hide the pending provider_delay, it will propagate to all chained
states -->
<attribute id="pending_provider_delay" _delta="define">
<hidden/>
</attribute>
</flags>
</state>
<state id="resolved" _delta="must_exist">
<flags>
<attribute id="pending_provider_delay" _delta="define">
<!-- Read_only takes precedence on hidden? -->
<read_only/>
</attribute>
</flags>
</state>
</states>
</lifecycle>
这是用户请求的结果,该请求已被移回三倍,并且在“已分配”和“待决提供者”之间施加了强制,结果是,“经过”不对应于“已开始”和“已停止”之间的差异。但是您可以看到7 * 60s + 49s = 469s,因为“花费的提供者时间”只是“经过的”子项(=耗时)的漂亮显示。
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-timespent.png
秒表的行为
在这一部分中,我们将展示用户要求的使用寿命
[*]秒表从未启动:
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-no-start.png2.首次将用户请求从“已分配”移到“待定”提供者:
[*]秒表正在运行,因此“经过”(=耗时)不可用
[*]“已启动”和“最后启动”相等
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-start.png3.首次将用户请求从“待处理提供者”移回“已分配”:
[*]秒表已停止,因此“经过”(=耗时)可用
[*]不运行时“ LastStart”为空
[*]已记录“已停止”
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-stop.png4.用户请求再次从“已分配”移动到“待处理提供者”:
[*]秒表正在运行,因此“经过”(=耗时)不可用
[*]“开始”不变
[*]“ LastStart”对应于秒表的最后启动时间
[*]运行时“停止”为空
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-second-start.png5.用户请求再次从“ Pending提供者”移回至Assigned:
[*]秒表已停止,因此“经过”(=耗时)可用
[*]“开始”不变
[*]由于秒表已停止,“ LastStart”再次为空
[*]再次记录“停止”,并与最后一站相对应
[*]请注意,“已用”不等于“已开始”和“已停止”之间的差异
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-second-stop.png
秒表是自动计算的,不能由用户编辑:
https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-edit.png
完整的XML
这是此教程的合并XML
[ ttps://www.itophub.io/wiki/page?do=export_code&id=2_7_0%3Acustomization%3Aadd-state&codeblock=11]itop_design
<classes>
<class id="UserRequest">
<fields>
<!-- Add a new state value to the existing status -->
<field id="status" _delta="must_exist">
<values>
<value id="pending_provider" _delta="define">pending_provider</value>
</values>
</field>
<!-- Add a stopwatch to count the timespent in this state -->
<field id="providerstopwatch" xsi:type="AttributeStopWatch" _delta="define">
<states>
<!-- this are the states, during which the stopwatch is counting time -->
<state id="pending_provider">pending_provider</state>
</states>
<working_time/>
<thresholds/>
<always_load_in_tables>true</always_load_in_tables>
</field>
<!-- Declaring this stopwatch sub-item is required to display or query it -->
<field id="pending_provider_delay" xsi:type="AttributeSubItem"
_delta="define">
<target_attcode>providerstopwatch</target_attcode>
<!-- Possible item_code: timespent, started, laststart, stopped-->
<item_code>timespent</item_code>
</field>
</fields>
<lifecycle>
<stimuli>
<!-- Add a new stimulus to switch to pending_provider state -->
<stimulus _delta="define" id="ev_pending_provider"
xsi:type="StimulusUserAction"/>
</stimuli>
<states>
<!-- This level define the state we are in -->
<state id="assigned" _delta="must_exist">
<transitions>
<!-- this define an available transition from the above state -->
<transition id="ev_pending_provider" _delta="define">
<!-- This define the stimulus which trigger the transition -->
<!-- on a given state there can only be one transition triggered by a
given stimulus -->
<stimulus>ev_pending_provider</stimulus>
<!-- This define on which state the UserRequest will end-up -->
<target>pending_provider</target>
<actions/>
</transition>
</transitions>
</state>
<!-- From the new state -->
<state id="pending_provider" _delta="define">
<flags /> <!-- Also empty it's a mandatory tag -->
<transitions>
<!-- we want to assign the ticket back to the support team -->
<transition id="ev_assign">
<stimulus>ev_assign</stimulus>
<target>assigned</target>
<actions/>
</transition>
</transitions>
<!-- The fields are the same as in "assigned" state -->
<inherit_flags_from>assigned</inherit_flags_from>
</state>
<state _delta="must_exist" id="new">
<flags>
<!-- Hide the pending provider_delay, it will propagate to all chained
states -->
<attribute id="pending_provider_delay" _delta="define">
<hidden/>
</attribute>
</flags>
</state>
<state id="resolved" _delta="must_exist">
<flags>
<attribute id="pending_provider_delay" _delta="define">
<!-- Read_only takes precedence on hidden? -->
<read_only/>
</attribute>
</flags>
</state>
</states>
</lifecycle>
<!-- Display the 2 new fields in the details of the UserRequest -->
<presentation>
<details _delta="must_exist">
<items>
<!-- First column of the UserRequest display -->
<item id="col:col0">
<items>
<item id="fieldset:Ticket:moreinfo">
<items>
<!-- Add the provider timespent delay -->
<item id="pending_provider_delay" _delta="define">
<rank>80</rank>
</item>
<!-- This displays a stopwatch (including some sub-items) -->
<!-- This will help you to understand how a stopwatch behave -->
<item id="providerstopwatch" _delta="define">
<rank>90</rank>
</item>
</items>
<rank>20</rank>
</item>
</items>
</item>
</items>
</details>
</presentation>
</class>
</classes>
<dictionaries>
<dictionary id="EN US">
<entries>
<!-- Give a label to the new state -->
<entry id="Class:UserRequest/Attribute:status/Value:pending_provider"
_delta="define">
<!]>
</entry>
<entry id="Class:UserRequest/Attribute:pending_provider_delay"
_delta="define">
<!]>
</entry>
<entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
<!]>
</entry>
<entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
<!]>
</entry>
</entries>
</dictionary>
</dictionaries>
页:
[1]