2
1
0

We are currently able to sync worklogs between two Jira instances. This include author, date, duration and description. However, we would like also to sync the Tempo related attributes along with it such as the Tempo Account and any other custom attributes that might be needed in the future. Just to be more specific, these attributes are saved in the worklog, not in the issue.


I can't seem to find information on this topic in the documenation, so I appreciate your support.

  1. Amr Hamza

    Both instances are Jira Server.

CommentAdd your comment...

1 answer

  1.  
    1
    0
    -1

    A good source of inspiration is available at
    https://library.adaptavist.com/collection/automate-daily-tempo-tasks-in-jira-with-scriptrunner


    You can extract account information from the customField - check for instance

    https://library.adaptavist.com/entity/display-account-lead-on-jira-issue


    These values can be transported using a customKey such as


    // untested code
    
    import com.tempoplugin.platform.jira.user.JiraTempoUser
    
    def account = issue.customFields.account.value
    replica.customKeys.accountLeadName = (account.lead as JiraTempoUser).applicationUser.name


    Not sure if it will work - especially with the import.

    1. Amr Hamza

      Hi Francis Martens (Exalate),


      Thanks for your reply.


      I guess what you are proposing is a way to somehow set the Account field or an account dependent field in Jira issue itself. However, what we are trying to achieve is to set the Account attribute in the Tempo Worklog.


      A usecase that might help understand our requirement is that we for example set the Account field in a Jira issue to the billable account of our customer by default. When we log work, the worklog captures the value of the Account field and displays it as a default value for the Accout attribute in the worklog.

      Sometimes it is decided that some worklogs are unbillable so we change the value of the Account attribute to the unbillable account. Now what would like to do:

      • Send only those billable worklogs to customer's Jira,
      • Or send all worklogs but include their Account attribute information so that the customer has also visibility to what is billable and what is not,

      Of course, because the accounts are different in both instances, we would like to create a mapping in the incoming sync rules.


      I hope this could clear the question a bit.


      Cheers,

      Amr

    2. Francis Martens (Exalate)

      OK - try it as follows



      /*
      ** First look up the attribute id for account through the workAttributeService
      **
      ** To get access to this service - lookup the class using the findClass method
      ** and then use the getOSGiComponentInstanceOfType to get the service itself
      ** (the throw is a handy trick to see if you get the results you expect
      */
      
      def workAttributeServiceClass = ComponentAccessor.pluginAccessor.classLoader.findClass("com.tempoplugin.core.workattribute.api.WorkAttributeService")
      def workAttributeService = ComponentAccessor.getOSGiComponentInstanceOfType(workAttributeServiceClass)
      //throw new Exception ("Work AttributeService  - ${workAttributeService.properties}")
      
      def accountAttribute = workAttributeService.getWorkAttributeByKey("_Account_").returnedValue
      
      /*
      ** Then look up the value of the attribute using the workAttributeValueService
      ** the approach is the same (lookup class, get the instance)
      */
      
      def workAttributeValueServiceClass = ComponentAccessor.pluginAccessor.classLoader.findClass("com.tempoplugin.core.workattribute.api.WorkAttributeValueService")
      def workAttributeValueService = ComponentAccessor.getOSGiComponentInstanceOfType(workAttributeValueServiceClass)
      def worklogs = issue.workLogs
      
      //throw new Exception ("Work AttributeService - ${workAttributeService.properties}")
      
      
      
      def worklogAccount = [:]
      
      issue.workLogs.each {
          
          worklog ->
      
          def attributeValue = workAttributeValueService.getWorkAttributeValueByWorklogAndWorkAttribute(worklog.id, accountAttribute.id).returnedValue    
          throw new Exception("Attribute value for ${worklog.properties} is ${attributeValue.properties}")
      }



      The loop will stop at the first exception - it unveils that following properties are available


      For worklog


      • created:Mon Aug 10 07:26:37 GMT 2020,
      • startDate:Mon Aug 10 00:00:00 GMT 2020,
      • traceType:WORKLOG,
      • comment:with AN1,
      • newEstimate:null,
      • updated:Mon Aug 10 07:26:37 GMT 2020, id:10300, idStr:10300,
      • timeSpent:36000,
      • locked:false,
      • remoteId:null,
      • remoteIdStr:null,
      • roleLevel:null,
      • class:class com.exalate.basic.domain.hubobject.v1.BasicHubWorkLog,
      • adjustmentMode:AUTO_ADJUST,
      • adjustRemainingBy:null,
      • groupLevel:null,
      • updateAuthor:{
        • @key : admin},
        • author:{ @key : admin}]


      And for attribute Account


      • billableAttribute:false,
      • workAttribute:com.tempoplugin.core.workattribute.api.WorkAttribute@ddd3ad72,
      • value:AN1,
      • class:class com.tempoplugin.core.workattribute.api.WorkAttributeValue,
      • systemType:false,
      • id:1,
      • numericAttribute:false,
      • numericValue:null,
      • worklogId:10300


      You should be to decide which worklogs should be sent to the other side using this approach.

      Let me know


    3. Amr Hamza

      Hi Francis Martens (Exalate),


      Many thanks for the solution.


      In the outgoing part it works now as expected. Only the billable worklogs are being sent.

      //Billable worklgs
      import com.atlassian.jira.component.ComponentAccessor
      
      def workAttributeServiceClass       = ComponentAccessor.pluginAccessor.classLoader.findClass("com.tempoplugin.core.workattribute.api.WorkAttributeService")
      def workAttributeValueServiceClass  = ComponentAccessor.pluginAccessor.classLoader.findClass("com.tempoplugin.core.workattribute.api.WorkAttributeValueService")
      def workAttributeService            = ComponentAccessor.getOSGiComponentInstanceOfType(workAttributeServiceClass)
      def workAttributeValueService       = ComponentAccessor.getOSGiComponentInstanceOfType(workAttributeValueServiceClass)
      
      def accountAttribute = workAttributeService.getWorkAttributeByKey("_Account_").returnedValue
      def worklogs = issue.workLogs
      def newWorklogs = []
      
      issue.workLogs.each {worklog ->
          def attributeValue = workAttributeValueService.getWorkAttributeValueByWorklogAndWorkAttribute(worklog.id, accountAttribute.id).returnedValue
          if (attributeValue.value == "CUSTOMER-Bill") {
              newWorklogs.add(worklog)
          }
      }
      
      replica.workLogs            = newWorklogs


      Now the question is how to set the worklog account attribute in the incoming sync rules. Thanks.


      Cheers,

      Amr

    4. Francis Martens (Exalate)

      Ha - exercise for the reader (smile)


      The core is to understand what api Tempo is providing, and then integrate it into your incoming sync script,

      Let me know if this is sufficient (we got a huge increase in evaluations and answering their questions is currently priority - hope you understand)


    5. Amr Hamza

      The problem is that Tempo doesn't have any publicly available Java API documentation that we can refer to. And while Adaptavist library is very helpful, it is still limited to examples and usecases. They don't cover everything.


      But no worries. I understand that you have more pressing matters.


      Thanks for your support so far (smile)


      Cheers,

      Amr

    CommentAdd your comment...