You can execute execute a Groovy script just before usual handling of Jira timesheet approval/rejection and stop the process by returning an error message. Returned message will be shown to the Jira user that is trying to approve/reject a timesheet. If you don’t return anything from this script normal approval/rejection workflow will run.

Within this script you can access Jira services, WorklogPRO services and services from other plugins. You can use TimesheetApprovalAction parameter to access approval related parameters.

Prevent Timesheet Approval/Rejection if Period is Open

if (timesheetApprovalAction.period.open) {
  return "Period is still open. You can't approve the timesheet when period is open."
}

Prevent Users to Approve/Reject Their Own Timesheet

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.JiraAuthenticationContext;

def authenticationContext = ComponentAccessor.getJiraAuthenticationContext();
def loggedInUser = authenticationContext.getLoggedInUser();

if (timesheetApprovalAction.userKey == loggedInUser.key) {
  return "You can't approve your own timesheet!"
}

Prevent Approval/Rejection of Timesheet if User Hasn’t Submitted it Yet

import com.deniz.jira.worklog.approval.*;
import com.atlassian.jira.component.ComponentAccessor;

//We need to load WorklogPRO classes differently using getOSGiComponentInstanceOfType
TimesheetApprovalService approvalService = ComponentAccessor.getOSGiComponentInstanceOfType(TimesheetApprovalService.class);

def approvalRequests = approvalService.getTsApprovalRequestsForUserAndPeriod(timesheetApprovalAction.userKey, timesheetApprovalAction.period.id);
if (approvalRequests.length == 0) {
  return "User hasn't submitted his/her timesheet yet!";
}

Don’t Allow Multiple Approval/Rejection for the Same Project and Period

import com.deniz.jira.worklog.approval.*;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.project.*;
import com.atlassian.jira.*;
import com.atlassian.jira.user.util.*;

TimesheetApprovalService approvalService = ComponentAccessor.getOSGiComponentInstanceOfType(TimesheetApprovalService.class);
UserManager userManager = ComponentAccessor.getUserManager();
ProjectManager projectManager = ComponentAccessor.getProjectManager();

def user = userManager.getUserByKey(timesheetApprovalAction.userKey);
def project = projectManager.getProjectByCurrentKey(timesheetApprovalAction.projectKey);

def approvalStatus = approvalService.getTimesheetApprovalStatus(user.getUsername(), timesheetApprovalAction.period.id, [project.id] as Set);

def projectApprovalStatus = approvalStatus.projectApproval.get(project.key);
if (projectApprovalStatus.approvalStatus != TimesheetApprovalStatus.SUBMITTED) {
  return "This timesheet is already approved/rejected or not submitted yet!"  
}

Require Explanation When Rejecting a Timesheet

import com.deniz.jira.worklog.approval.*;
import com.atlassian.jira.component.ComponentAccessor;

def boolean emptyExplanation = timesheetApprovalAction.explanation == null || timesheetApprovalAction.explanation.trim().length() == 0;
if (timesheetApprovalAction.action.equals("REJECT") && emptyExplanation) {
  return "You need to specify a reason for timesheet rejection!"
}