Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
def issue = worklog.getIssue();
def remainingEstimate=issue.getEstimate();
if (remainingEstimate== null || remainingEstimate == 0 ) { //no remaining estimate on issue, don't allow logging work
  return "Can't log work because the remaining estimate is '0' or 'Not Specified'";
}

Don't Allow Logging Work

...

Following scripts do not allow any worklog to be higher than remaining estimate of an issue. If there is no remaining estimate, users can log any duration.

...

languagegroovy

If Original Estimate is Zero or Not Specified

This script prevents the worklog entry to an issue belonging to the ATP project in case the value of the original estimate field is null or zero.

Code Block
import com.deniz.jira.worklog.*;
def issue = worklog.getIssue();
def ifproject = (issue.getEstimategetProject().key;
def originalEstimate == nullissue.getOriginalEstimate();
{def //nooriginalEstimateCheck estimate= on issue, allow logging work
  return;
}
if (issue.getEstimate() < worklog.getTimeSpent()) !originalEstimate || originalEstimate == 0;
if(project == "ATP" && originalEstimateCheck){
  return "MaximumCan duration younot can log is work!" + issue.getEstimate;
}

Don't Allow Logging Work Higher Than Remaining Estimate

Following scripts do not allow any worklog to be higher than remaining estimate of an issue. If there is no remaining estimate, users can log any duration.

Code Block
languagegroovy
def issue = worklog.getIssue();
if (issue.getEstimate() == null) { //no estimate on issue, allow logging work
  return;
}
if (issue.getEstimate() < worklog.getTimeSpent()) {
  return "Maximum duration you can log is " + issue.getEstimate() / 60 + " minute(s)"
}

Don't allow logging work on issues which has subtasks

...

Code Block
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;
import java.text.SimpleDateFormat;
import java.time.Duration;
 
def authenticationContext = ComponentAccessor.getJiraAuthenticationContext();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", authenticationContext.getLocale());
 
def issue = worklog.getIssue();
def dueDate = issue.getDueDate(); //2020-04-22 00:00:00, due dates default to 00:00:00
if (dueDate != null) {
  def dueDateNight = Date.from(dueDate.toInstant().plus(Duration.ofHours(23)).plus(Duration.ofMinutes(59))); //20-04-22 23:59:0000
   
  //the date on which work is performed, not the day worklog is created
  def workStartDate = worklog.getStartDate();
   
  //theIf dateyou onneed whichto workconsider istimezone performed,differences notof theusers dayyou worklogmay iswant createdto use LocalDateTime
def workStartDate =if worklog(workStartDate.getStartDateafter();
   
  //If you need to consider timezone differences of users you may want to use LocalDateTime
  if (workStartDate.after(dueDateNight)) {
    return "You can't specify a work start date after " + simpleDateFormat.format(dueDate);
  } 
}

Don't Allow Worklog After a Specific Date Specified on Issue

Code Block
import com.atlassian.jira.security.groups.GroupManager
import com.atlassian.jira.component.ComponentAccessor
 
def cfm = ComponentAccessor.getCustomFieldManager()
def issue = worklog.getIssue()
def endDateField = cfm.getCustomFieldObject('customfield_11300') //custom field id of date field we are interested
def endDate = endDateField.getValue(issue) as Date
 
if (worklog.getStartDate() > endDate + 1){
    return "You can only log time before or during ${endDate.format('dd.MM.yyyy')}"
}

Don't Allow a User to Log Overlapping Worklogs

Code Block
import com.atlassian.jira.issue.worklog.*;
import java.time.*;
import java.time.temporal.*;
import com.deniz.jira.worklog.services.*;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;
 
def timesheetService = ComponentAccessor.getOSGiComponentInstanceOfType(TimesheetService.class);
 
def issue = worklog.getIssue();
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();
def newWorklogStart = ZonedDateTime.ofInstant(worklog.getStartDate().toInstant(), ZoneId.systemDefault());
ZonedDateTime startTime = newWorklogStart.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime endTime = newWorklogStart.plusSeconds(worklog.timeSpent);
 
def newWorklogStartInMilis = newWorklogStart.toInstant().toEpochMilli();
def newWorklogEndInMilis = newWorklogStart.toInstant().plusSeconds(worklog.timeSpent).toEpochMilli();
 
def worklogWrapper = timesheetService.getUsersWorklogs(startTime, endTime, true, null, null, null, null, currentUser.getUsername());
 
def errorMessage = null;
worklogWrapper.projects.each { project ->
  project.issues.each { wIssue ->
    wIssue.workLogs.each { pWorklog ->dueDateNight)) {
    return "You can't specify a work start date after " + simpleDateFormat.format(dueDate);
  } 
}

Don't Allow Worklog After a Specific Date Specified on Issue

Code Block
import com.atlassian.jira.security.groups.GroupManager
import com.atlassian.jira.component.ComponentAccessor

def cfm = ComponentAccessor.getCustomFieldManager()
def issue = worklog.getIssue()
def endDateField = cfm.getCustomFieldObject('customfield_11300') //custom field id of date field we are interested
def endDate = endDateField.getValue(issue) as Date
if(endDate){
  if (worklog.getStartDate() > endDate + 1){
    return "You can only log time before or during ${endDate.format('dd.MM.yyyy')}"
  }
}

Don't Allow a User to Log Overlapping Worklogs

Code Block
import com.atlassian.jira.issue.worklog.*;
import java.time.*;
import java.time.temporal.*;
import com.deniz.jira.worklog.services.*;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;
 
def timesheetService = ComponentAccessor.getOSGiComponentInstanceOfType(TimesheetService.class);
 
def issue = worklog.getIssue();
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();
def newWorklogStart = ZonedDateTime.ofInstant(worklog.getStartDate().toInstant(), ZoneId.systemDefault());
ZonedDateTime startTime = newWorklogStart.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime endTime = newWorklogStart.plusSeconds(worklog.timeSpent);
 
def newWorklogStartInMilis = newWorklogStart.toInstant().toEpochMilli();
def newWorklogEndInMilis = newWorklogStart.toInstant().plusSeconds(worklog.timeSpent).toEpochMilli();
 
def worklogWrapper = timesheetService.getUsersWorklogs(startTime, endTime, true, null, null, null, null, currentUser.getUsername());
 
def errorMessage = null;
worklogWrapper.projects.each { project ->
  project.issues.each { wIssue ->
    wIssue.workLogs.each { pWorklog ->
      if (pWorklog.id != worklog.id) {
          def pWorkStartInMilis = pWorklog.workStart.toInstant().toEpochMilli();
          def pWorkEndInMilis = pWorklog.workStart.toInstant().plusSeconds(pWorklog.getTimeSpent()).toEpochMilli();
          if (pWorklog.id != worklog.id) {
      ((newWorklogStartInMilis >= pWorkStartInMilis && newWorklogStartInMilis <= pWorkEndInMilis) ||
   def pWorkStartInMilis = pWorklog.workStart.toInstant().toEpochMilli();        (newWorklogStartInMilis <= pWorkEndInMilis def&& pWorkEndInMilisnewWorklogEndInMilis >= pWorklog.workStart.toInstant().plusSeconds(pWorklog.getTimeSpent()).toEpochMilli();pWorkStartInMilis)) {
           if ((newWorklogStartInMiliserrorMessage >= pWorkStartInMilis && newWorklogStartInMilis <= pWorkEndInMilis) ||
   "Collides with worklog which started on " + pWorklog.workStart.toString() + ". Please check your timesheet.";
          (newWorklogStartInMilis}
<= pWorkEndInMilis && newWorklogEndInMilis >= pWorkStartInMilis)) {}
    }
  }
}
 
return errorMessage = "Collides with worklog which started on " + pWorklog.workStart.toString() + ". Please check your timesheet.";
          }
      }
    }
  }
}
 
return errorMessage;

Don’t Allow Non Service Desk Users to Create Worklogs

Code Block
languagegroovy
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.security.roles.ProjectRoleManager;
import com.deniz.jira.worklog.services.attr.AttrTypeService;

def authenticationContext = ComponentAccessor.getJiraAuthenticationContext();
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager.class);

//We need to load WorklogPRO classes differently using getOSGiComponentInstanceOfType
def attrTypeService = ComponentAccessor.getOSGiComponentInstanceOfType(AttrTypeService.class);

def billableAttrType = attrTypeService.getAttrTypeWithName("Billable").get();
if (billableAttrType == null) {
  return; //there is no billable attribute
}

def isBillable = worklogAttributes.get(billableAttrType.getID());
def loggedInUser = authenticationContext.getLoggedInUser();
def serviceDeskTeamRole = projectRoleManager.getProjectRole("Service Desk Team");
def project = worklog.getIssue().getProjectObject();

println(worklogAttributes);

if (isBillable == "yes") { //boolean attributes are has either "no" or "yes" value.
  if (!projectRoleManager.isUserInProjectRole(loggedInUser, serviceDeskTeamRole, project)) ;

Don’t Allow Non Service Desk Users to Create Worklogs

Code Block
languagegroovy
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.security.roles.ProjectRoleManager;
import com.deniz.jira.worklog.services.attr.AttrTypeService;

def authenticationContext = ComponentAccessor.getJiraAuthenticationContext();
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager.class);

//We need to load WorklogPRO classes differently using getOSGiComponentInstanceOfType
def attrTypeService = ComponentAccessor.getOSGiComponentInstanceOfType(AttrTypeService.class);

def billableAttrType = attrTypeService.getAttrTypeWithName("Billable").get();
if (billableAttrType == null) {
  return; //there is no billable attribute
}

def isBillable = worklogAttributes.get(billableAttrType.getID());
def loggedInUser = authenticationContext.getLoggedInUser();
def serviceDeskTeamRole = projectRoleManager.getProjectRole("Service Desk Team");
def project = worklog.getIssue().getProjectObject();

println(worklogAttributes);

if (isBillable == "yes") { //boolean attributes are has either "no" or "yes" value.
  if (!projectRoleManager.isUserInProjectRole(loggedInUser, serviceDeskTeamRole, project)) {
    return "Only Service Desk Team can register billable worklogs!"
  }
}

Don't Allow Worklog Without Comment Except for Defined Projects

Code Block
import com.deniz.jira.worklog.*;
def worklogComment = worklog.comment;
def issue = worklog.getIssue();
def workloggedProject = issue.getProject().key.toString();
def exemptProjects= ["ATP", "SP"];

if(!exemptProjects.contains(workloggedProject) && !worklogComment){
    return "OnlyComment Service Desk Team can register billable worklogs!"
  }is required.";
}