等待第三方的工单

决条件:您必须熟悉教程中使用的语法 并且已经创建了一个扩展.

学习:将状态添加到生命周期和计数中花费的时间

水平:高级

域:XMLStopwatchAutomationLifecycle 

最低版本:2.3.0

在此教程中,我们要标识支持团队正在等待第三方提供者信息操作的工单,如果没有该工单,则无法在工单上工作。为了实现这一目标,我们将:

  1. 向UserRequest添加新状态,表明我们正在等待第三方提供者
  2. 添加新的激励,以将用户请求移动到该新状态
  3. 添加两个过渡,以允许将UserRequest移入和移出该新状态

在第二步中,我们要跟踪每个工单上等待提供者花费的时间。这要求:

  1. 当工单处于“ pending_provider”状态时,将UserRequest类上的秒表属性添加到计数。
  2. 添加一个子项字段以显示等待提供者所花费的时间。
  3. 仅在UserRequest的某些状态下显示等待第三方提供者花费的总时间

声明一个新状态

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>
itop_design / dictionaries / dictionary@EN US
 
  <!-- Give a label to the new state -->
  <entry id="Class:UserRequest/Attribute:status/Value:pending_provider" _delta="define">
    <![CDATA[Pending provider]]>
  </entry>
  • 请注意枚举价值的字典代码逻辑:类:<class_name >>属性:<属性_code >>价值:<价值_code>

添加刺激

该刺激与按钮和“其他操作活动”菜单相对应,当功能成为可能时,将在UserRequest的详细信息上提出该菜单。

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>
itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
    <![CDATA[Wait for Provider]]>
  </entry>
  • 注意刺激的字典代码逻辑:Class:UserRequesttStimulus:stimulus_id
  • 使用该刺激,刺激的标签将应用于所有过渡。
  • 通常,给定的刺激总是会停留在相同的状态。
  • 刺激声明没有指定如何使用,它可以用于任何状态之间的任何转换。

如果您需要为两个过渡使用不同的标签,请创建两个不同的刺激

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-menu.png

添加状态和过渡

转换的定义是:

  1. 起始状态
  2. 刺激,它会触发转换,并在启动状态下建议作为可能的功能
  3. 结束状态,即对象在转换之后的结果状态

在这里,我们要提出两个可能的过渡:

  1. 使用新创建的刺激“ ev_pending_provider”,将一个转换从“已分配”状态更改为“ pending_provider”状态。支持团队等待第三方提供者采取行动并做出响应时,将使用它。
  2. 一个转换使用经典的“ ev_assign”刺激从“ pending_provider”返回到“分配”。提供者已完成操作并且支持团队可以与提供者解决一起使用时,将使用它。
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

计数等待第三方的时间

在这个补充用例中,我们要跟踪每个工单上等待提供者花费的时间。为此,我们将

  1. 当工单处于“ pending_provider”状态时,将UserRequest类上的秒表属性添加到计数。
  2. 添加一个子项字段以显示等待提供者所花费的时间。
  3. 仅在UserRequest的某些状态下显示等待第三方提供者花费的总时间

添加秒表

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>
itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
    <![CDATA[Provider stopwatch]]>
  </entry>
  • 这是秒表的最简单用法,只计算在特定状态下花费的时间

追踪花费的时间

必须执行此步骤,才能通过OQL在表单和查询中显示此信息。

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>

您还可以声明其他子项目。

itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Attribute:pending_provider_delay" _delta="define">
    <![CDATA[Provider time spent]]>
  </entry>

显示秒表

在此示例中,我们将自行显示秒表。此字段非常特殊,因为它是一个复合字段,它包含所有子信息,这些子信息都已显示。我们已决定始终显示秒表,而不管它是否正在运行。您将看到显示的数据在某些状态下将不可用。

假设您已经声明了子项目,那么子项目也可以独立显示,就像我们为子项目花费的时间所做的一样。因此,我们还将显示花费的时间。

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”状态显示,因为它没有提供准确的信息
  • 我们决定不将其显示为“新”状态,因为它无用且为空
  • 我们决定在工单是被解决或已关闭时以只读方式显示它,因为用户不应修改它。

我们在演示文稿中定义了该字段需要显示的位置,现在我们可以通过为每个状态定义该字段是隐藏还是只读来调整何时应该可用。

  • 当我们将字段定义为在新状态下隐藏时,因为状态链接在标准数据模型中,因此这会传播到以下所有状态。
  • 当我们在状态被解决中将其定义为只读时,它将覆盖隐藏标志
  • 当已关闭更改为被解决状态时,它仍然可见
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,因为“花费的提供者时间”只是“Elapsed” sub-item (=timespent)的漂亮显示。

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-timespent.png

秒表的行为

在这一部分中,我们将展示用户要求的使用寿命

  1. 秒表从未启动:

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-no-start.png

2.首次将用户请求从“已分配”移到“待定”提供者:

  • 秒表正在运行,因此 “Elapsed” (= timespent)不可用
  • “已启动”和“最后启动”相等

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-start.png

3.首次将用户请求从“待处理提供者”移回“已分配”:

  • 秒表已停止,因此“Elapsed” (= timespent) 可用
  • LastStart“ LastStart”在未运行时为空
  • Stopped“已停止”

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-stop.png

4.用户请求再次从“已分配”移动到“待处理提供者”:

  • 秒表正在运行,因此 “Elapsed” (= timespent) 不可用
  • “Started”不变
  • “ LastStart”对应于秒表的最后启动时间
  • 运行时“Stopped”为空

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-second-start.png

5.用户请求再次从“ Pending提供者”移回至Assigned:

  • 秒表已停止,因此 “Elapsed” (= timespent) 可用
  • “Started”不变
  • 由于秒表已停止,“ LastStart”再次为空
  • 再次记录“Stopped”,并与最后一站相对应
  • 请注意,“已用”不等于“Started” and “Stopped”之间的差异

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

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">
        <![CDATA[Pending provider]]>
      </entry>
      <entry id="Class:UserRequest/Attribute:pending_provider_delay" _delta="define">
        <![CDATA[Provider time spent]]>
      </entry>
      <entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
        <![CDATA[Wait for Provider]]>
      </entry>
      <entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
        <![CDATA[Provider stopwatch]]>
      </entry>
    </entries>
  </dictionary>
</dictionaries>

原贴链接:https://www.itophub.io/wiki/page?id=2_7_0%3Acustomization%3Aadd-state


Flag Tickets waiting for a 3rd party

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Add a state to a lifecycle and count time spent in it
level:
Advanced
domains:
XMLStopwatchAutomationLifecycle
min version:
2.3.0

In this tutorial, we want to identify Tickets for which the support team is waiting for a 3rd party provider information/action, and cannot work on the ticket without it. In order to achieve this goal, we will:

  1. Add a new state to the UserRequest, indicating that we are waiting for the 3rd party provider

  2. Add a new stimulus, to move a User Request in that new state

  3. Add two transitions, to allow the UserRequest to be moved to and out of this new state

In a second step we want to track how much time was spent waiting for the provider on each ticket. This requires to:

  1. Add a stopwatch attribute on UserRequest class, to count when the ticket is in “pending_provider” state.

  2. Add a sub-item field to display the time spent while waiting for provider.

  3. Display the total time spent waiting for the 3rd party provider only in some states of the UserRequest

Declare a new state

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>
itop_design / dictionaries / dictionary@EN US
 
  <!-- Give a label to the new state -->
  <entry id="Class:UserRequest/Attribute:status/Value:pending_provider" _delta="define">
    <![CDATA[Pending provider]]>
  </entry>
  • Note the dictionary code logic for an enum value: Class:<class_name>/Attribute:<attribute_code>/Value:<value_code>

Add a stimulus

The stimulus correspond to the button and “Other actions” menu which will be proposed on the details of the UserRequest, when this action will be possible.

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>
itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
    <![CDATA[Wait for Provider]]>
  </entry>
  • Note the dictionary code logic for a stimulus: Class:UserRequest/Stimulus:stimulus_id

  • The label of a stimulus is applied on all transitions using this stimulus.

  • In general a given stimulus always end-up on the same state.

  • The stimulus declaration does not specify how it will be used, it can be used for any transition between any states.

If you need to have a different label for two transitions, then create two different stimulus

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-menu.png

Add state and transitions

A transition is defined by:

  1. a starting state,

  2. a stimulus, which triggers the transition and is proposed as a possible action on the starting state

  3. an ending state, which is the resulting state in which the object will be after the transition

Here we want to propose two possible transitions:

  1. One transition from the “assigned” to “pending_provider” state using the newly created stimulus “ev_pending_provider”. It will be used when the support team is waiting for the 3rd party provider to act and respond.

  2. One transition to go back from “pending_provider” to “assigned” using the classic “ev_assign” stimulus. It will be used when provider has replied/act and that support team can go on with the Ticket resolution.

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>

When you define a new state, you don't need to redefine for each and every field, if that field, should be read_only, hidden or mandatory in this state. You can just say that it inherits from another state and describe the difference under a <flags> tag. See this tutorial for example: Force a field to be mandatory by lifecycle

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-transition.png

Counting time waiting for 3rd party

In this complementary usecase, we want to track how much time was spent waiting for the provider on each ticket. For this we will

  1. Add a stopwatch attribute on UserRequest class, to count when the ticket is in “pending_provider” state.

  2. Add a sub-item field to display the time spent while waiting for provider.

  3. Display the total time spent waiting for the 3rd party provider only in some states of the UserRequest

Add a stopwatch

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>
itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
    <![CDATA[Provider stopwatch]]>
  </entry>
  • This is the simplest use you can make of a stopwatch, just counting time spent in particular states

Track time spent

This step is mandatory to be able to display this information in a form and query it by OQL.

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>
itop_design / dictionaries / dictionary@EN US / entries
 
  <entry id="Class:UserRequest/Attribute:pending_provider_delay" _delta="define">
    <![CDATA[Provider time spent]]>
  </entry>

Display Stopwatch

In this example, we will display the stopwatch it-self. This field is rather special as it is a composite one, it contains sub-information, which are all displayed. We have decided to display the stopwatch all the time, regardless if it is running or not. You will see that the displayed data will not be available in some state.

Sub-items can also be displayed independently, assuming you have declared them, as we just did for the sub-item timespent. So we will also display the time spent.

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

Display time spent

Because the time spent is only calculated when the stopwatch is stopping - so here when the UserRequest exits the “pending_provider” state -

  • it should not be displayed in state “pending_provider”, as it does not provide an accurate information

  • we decided not to display it in state “new”, as it's useless and empty

  • we decided to display it when the ticket is resolved or closed, in read only as it should not be modified by the user.

We have defined in the presentation, where that field need to be displayed, now we can modulate when it should be available, by defining for each state, if this field should be hidden or read only.

  • When we define a field to be hidden in state new, as states are chained in standard datamodel, this propagates to all following states.

  • When we define it to be read only in state resolved, it overwrites the hidden flag

  • As closed is changed to resolved state, it is still visible

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>

Here is the result on a User Request for which was moved three time back and force between “Assigned” and “Pending provider”, as a result, “Elapsed” does not correspond to the difference between “Started” and “Stopped”. But you can see that 7*60s + 49s = 469s, as “Provider time spent” is just a nice display of the “Elapsed” sub-item (=timespent)

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-timespent.png

Behavior of the Stopwatch

In this part, we will show what the stopwatch contains along the User Request life

1. Stopwatch never started:https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-no-start.png

2. User Request is moved from “Assigned” to Pending provider for the first time:

  • stopwatch is running, so “Elapsed” (= timespent) is not available

  • “Started” and “LastStart” are equal

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-start.png

3. User Request is moved back from “Pending Provider” to Assigned for the first time:

  • stopwatch is stopped, so “Elapsed” (= timespent) is available

  • “LastStart” is empty when not running

  • “Stopped” is documented

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-first-stop.png

4. User Request is moved again from “Assigned” to Pending provider:

  • stopwatch is running, so “Elapsed” (= timespent) is not available

  • “Started” is unchanged

  • “LastStart” correspond to the last time the stopwatch has started

  • “Stopped” is empty when running

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-second-start.png

5. User Request is moved back again from “Pending Provider” to Assigned:

  • stopwatch is stopped, so “Elapsed” (= timespent) is available

  • “Started” is unchanged

  • “LastStart” is empty again, as the stopwatch is stopped

  • “Stopped” is documented again and correspond to the last stop

  • Note that “Elapsed” is not equal to the difference between “Started” and “Stopped”

https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-second-stop.png

A stopwatch is automatically computed and cannot be edited by a user:https://www.itophub.io/wiki/media?media=2_7_0%3Acustomization%3Alifecycle-stopwatch-edit.png

Full XML

Here is the consolidated XML for this tutorial

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">
        <![CDATA[Pending provider]]>
      </entry>
      <entry id="Class:UserRequest/Attribute:pending_provider_delay" _delta="define">
        <![CDATA[Provider time spent]]>
      </entry>
      <entry id="Class:UserRequest/Stimulus:ev_pending_provider" _delta="define">
        <![CDATA[Wait for Provider]]>
      </entry>
      <entry id="Class:UserRequest/Attribute:providerstopwatch" _delta="define">
        <![CDATA[Provider stopwatch]]>
      </entry>
    </entries>
  </dictionary>
</dictionaries>

2_7_0/customization/add-state.txt · Last modified: 2020/04/15 15:23 (external edit)

Back to top

Table of Contents

标签:
由 superadmin 在 2020/08/27, 17:27 创建
    

需要帮助?

如果您需要有关XWiki的帮助,可以联系:

深圳市艾拓先锋企业管理咨询有限公司