Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to restrict logging work log for previous month

Hi,

Can we restrict the user from logging work for previous month. As per the scenario, I am trying to disable the time spent field in the Log Work Screen, if the Date Started is having a value of previous month. I tried behavior but in vain. Here is my script that I am trying to write using a listener:

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.fields.CustomField;
import com.onresolve.jira.groovy.user.FormField
import com.atlassian.jira.issue.worklog.*
import com.atlassian.jira.issue.MutableIssue

CustomField timespentField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Time Spent")
CustomField startDateField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Date Started")
def today=new Date().format("yyyy-MM-dd")
//def issue = event.issue as Issue
MutableIssue issue = event.issue as MutableIssue
//def startDateVal = issue.getCustomFieldValue(startDateField) as Date
log.error(issue.getCustomFieldValue(startDateField))
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def change = event?.getChangeLog()?.getRelated("ChildChangeItem").find {it.field == "Date Started"}
log.error("change is "+ change)
if(change){
    def startDateVal = issue.getCustomFieldValue(startDateField) as Date
    log.error("start date is "+ startDateVal)
    def month=startDateVal.format("MM")
    def year=startDateVal.format("yyyy")
    Calendar cacheCalendar = Calendar.instance
    cacheCalendar.set(Calendar.MONTH, (Integer.parseInt(month)+1));
    cacheCalendar.set(Calendar.YEAR, Integer.parseInt(year));
    def cutoffDate=cacheCalendar.time.format("yyyy-MM-05")
    def monthStart=startDateVal.format("yyyy-MM-01")
    log.error("Month Start:"+monthStart+"....cutOffDate:"+cutoffDate)
    if(monthStart<=today && today<cutoffDate){
              timespentField.hide();
        issue.timespentField.setVisible(false)
    }
    else {
       getFieldById("log-work-time-logged").setHidden(false)
       timespentField.setRequired(false)
    }
}

Any help will be highly appreciated.

5 answers

1 accepted

0 votes
Answer accepted

Hi,

I was able to resolve the problem with script listener.

Logic: Whenever work is logged with a date older than 30 days, we update the worklog date to current date.

Script Listener Events: Issue Worklog Updated, Work Logged on Issue

Script:


import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import java.lang.Object
import com.atlassian.jira.issue.worklog.WorklogImpl2
import java.text.SimpleDateFormat
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.worklog.DefaultWorklogManager
import com.atlassian.jira.security.roles.ProjectRoleManager
import com.atlassian.jira.issue.worklog.Worklog
import com.atlassian.jira.datetime.LocalDate
import com.atlassian.jira.issue.worklog.*

def issue = event.issue as Issue
WorklogManager worklogManager = ComponentAccessor.getWorklogManager()
List worklogs = worklogManager.getByIssue(issue)
def last_worklog=worklogs.last()
def author = last_worklog.getAuthorKey()
def dateformat= new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
def componentManager = ComponentManager.getInstance()
ProjectRoleManager projectRoleManager = ComponentManager.getComponentInstanceOfType(ProjectRoleManager.class) as ProjectRoleManager
def UsersRole = projectRoleManager.getProjectRole("Users")
long timespent = 1
def last_logged=last_worklog.getTimeSpent()
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -30);
Date todate1 = cal.getTime();    
def date_limit = dateformat.format(todate1);
def last_worklog_date=dateformat.format(last_worklog.getStartDate())
log.error(dateformat.parse(last_worklog_date).before(dateformat.parse(date_limit)))
if(last_worklog.getTimeSpent()>1 && dateformat.parse(last_worklog_date).before(dateformat.parse(date_limit))){
String comment=last_logged+'sec logged by '+author+' on date '+last_worklog_date
def worklog = new WorklogImpl2(issue, last_worklog.getId(), author, comment, new Date(), null, null,last_logged, UsersRole)
    worklogManager.update(issue.reporter, worklog, 0L, true)  
}

 

Thanks,

Sadaf Jabin

Hi How can restrict by Future Date to team log the work?

HI Prasanth,

Could you please elaborate the problem statement.

Thanks,
Sadaf Jabin

My team members are logging work hours for Future date how can we restrict this.

hi Prasanth,

Kindly remove the below line of code from the script:

Calendar cal = Calendar.getInstance();
//cal.add(Calendar.DATE, -30); ---> this makes the limit as 30 days prior to the current date. Commenting it out would make the restriction limit as the current date.
Date todate1 = cal.getTime();  

Like Руслан likes this

Hi @Sadaf Jabin ,

 

I am able to add future dates even I added the script below:

import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import java.lang.Object
import com.atlassian.jira.issue.worklog.WorklogImpl2
import java.text.SimpleDateFormat
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.worklog.DefaultWorklogManager
import com.atlassian.jira.security.roles.ProjectRoleManager
import com.atlassian.jira.issue.worklog.Worklog
import com.atlassian.jira.datetime.LocalDate
import com.atlassian.jira.issue.worklog.*
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.user.ApplicationUser

def issueManager = ComponentAccessor.getIssueManager()
def user= ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
MutableIssue issue = event.issue as MutableIssue

WorklogManager worklogManager = ComponentAccessor.getWorklogManager()
List worklogs = worklogManager.getByIssue(issue)
def last_worklog=worklogs.last()
def author = last_worklog.getAuthorKey()
def dateformat= new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
//IssueManager issueManager = ComponentAccessor.getIssueManager();
//def projectRoleManager = ComponentAccessor.getGroupManager()
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
//ProjectRoleManager projectRoleManager = issueManager.getComponentInstanceOfType(ProjectRoleManager.class) as ProjectRoleManager
def UsersRole = projectRoleManager.getProjectRole("Users")
long timespent = 1
def last_logged=last_worklog.getTimeSpent()
Calendar cal = Calendar.getInstance();
//cal.add(Calendar.DATE, -30);
Date todate1 = cal.getTime();
def date_limit = dateformat.format(todate1);
def last_worklog_date=dateformat.format(last_worklog.getStartDate())
log.error(dateformat.parse(last_worklog_date).before(dateformat.parse(date_limit)))
if(last_worklog.getTimeSpent()>1 && dateformat.parse(last_worklog_date).before(dateformat.parse(date_limit))){
String comment=last_logged+'sec logged by '+author+' on date '+last_worklog_date
def worklog = new WorklogImpl2(issue, last_worklog.getId(), author, comment, new Date(), null, null,last_logged, UsersRole)
worklogManager.update(issue.reporter, worklog, 0L, true)
}

 

Thanks,

Swarna

@Swarna Radha  Please provide the logs from the listener after entering a future date. Also request you to share the screenshot of the worklog tab for the issue where the efforts are being logged.

Hi @Sadaf Jabin ,

 

Please find attached screenshots of worklog tab and log of listener.

Log Time 2.pngLog time.pngLogs in Listener.png

HI @Swarna Radha ,

The code works fine for me. I have added few logs in the code, please update and share the latest log.

def issueManager = ComponentAccessor.getIssueManager()
def user= ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
MutableIssue issue = event.issue as MutableIssue

WorklogManager worklogManager = ComponentAccessor.getWorklogManager()
List worklogs = worklogManager.getByIssue(issue)
def last_worklog=worklogs.last()
def author = last_worklog.getAuthorKey()
def dateformat= new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
//IssueManager issueManager = ComponentAccessor.getIssueManager();
//def projectRoleManager = ComponentAccessor.getGroupManager()
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
//ProjectRoleManager projectRoleManager = issueManager.getComponentInstanceOfType(ProjectRoleManager.class) as ProjectRoleManager
def UsersRole = projectRoleManager.getProjectRole("Users")
long timespent = 1
def last_logged=last_worklog.getTimeSpent()
Calendar cal = Calendar.getInstance();
//cal.add(Calendar.DATE, -30);
Date todate1 = cal.getTime();
def date_limit = dateformat.format(todate1);
def last_worklog_date=dateformat.format(last_worklog.getStartDate())
log.error(dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date)))
log.error(date_limit)
log.error(last_worklog_date)
if(last_worklog.getTimeSpent()>1 && dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date))){
String comment=last_logged+'sec logged by '+author+' on date '+last_worklog_date
log.error(comment)
def worklog = new WorklogImpl2(issue, last_worklog.getId(), author, comment, new Date(), null, null,last_logged, UsersRole)
worklogManager.update(issue.reporter, worklog, 0L, true)
}

@Sadaf Jabin  What is a script listener? Is it an app extension?

@Hitesh_GoenkaThis is a script extension we get on installing the scriptrunner plugin.

0 votes

Hi 

 

Any one help me to disable to edit work log entry 

Thanks for the update Sadaf.

I tried the same and it is allowing me to log hours for the April Month, at the same time the code also got executed successfully. PFA screen shot for reference. 

Could you please let me know, where do we can see the logs now, Since the code was executed successfully right.

Future_Date_LogWork_2.jpg

@mvinod Can you please share the screenshot of the worklog tab of the issue where you logged the effort.  Th work will be logged successfully but the worklog date will appear as the current date.

@Sadaf Jabin  It seems like the date was get updated in the work log tab with the user selected date.

PFB screen shots

WorkLog_1.jpg

 

Listener Log Screen

 

Listener_Log.jpg

@Sadaf Jabin  Could you please let us know , how to debug this code or where to see the logger value which was get executed by this Custom Listener

@mvinodyou can click on the green check mark. It will bring up the logs. Please add the logs around the fields you are using in the conditions.

Thank you , Sadaf.

Now, I able to view the log details and listed below the screen shots for reference. Let me start to debug the code to make it work as expected and will let you know, if i need any other inputs.

 

Log_Screen_1.jpg

@Sadaf Jabin 

is it possible to throw error message in the UI Log Work screen itself based on the user selected date validation and i have listed below the screen shot for the same.

 

WorkLog_2.jpg

@Sadaf Jabin 

I referred few blogs and came to know that it is not possible to display error message in UI through Listener.

I re-used your code and am not sure about the logic where you have implemented the future date validation. Since it is always falls into the else block and I have a query here, Instead of updating the future date hours into the current date. Is it possible to disabling the process of updating the hours into the current date. In that case we can restrict the user to log the hours for the future date 

import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.component.pico.ComponentManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import java.lang.Object
import com.atlassian.jira.issue.worklog.WorklogImpl2
import java.text.SimpleDateFormat
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.worklog.DefaultWorklogManager
import com.atlassian.jira.security.roles.ProjectRoleManager
import com.atlassian.jira.issue.worklog.Worklog
import com.atlassian.jira.datetime.LocalDate
import com.atlassian.jira.issue.worklog.*

def issueManager = ComponentAccessor.getIssueManager()
def user= ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
log.error("user -> " + user);
MutableIssue issue = event.issue as MutableIssue

WorklogManager worklogManager = ComponentAccessor.getWorklogManager()
List worklogs = worklogManager.getByIssue(issue)
def last_worklog=worklogs.last()
//log.error("last_worklog -> " + last_worklog);
def author = last_worklog.getAuthorKey()
log.error("author -> " + author);
def dateformat= new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
//IssueManager issueManager = ComponentAccessor.getIssueManager();
//def projectRoleManager = ComponentAccessor.getGroupManager()
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
//ProjectRoleManager projectRoleManager = issueManager.getComponentInstanceOfType(ProjectRoleManager.class) as ProjectRoleManager
def UsersRole = projectRoleManager.getProjectRole("Users")
log.error("UsersRole -> " + UsersRole);
long timespent = 1
def last_logged=last_worklog.getTimeSpent()
log.error("last_logged -> " + last_logged);
Calendar cal = Calendar.getInstance();
//cal.add(Calendar.DATE, -30);
Date todate1 = cal.getTime();
log.error("todate1 -> " + todate1);
def date_limit = dateformat.format(todate1);
log.error("date_limit -> "+date_limit)
def last_worklog_date=dateformat.format(last_worklog.getStartDate())
log.error("last_worklog_date -> "+last_worklog_date)

log.error("dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date)) -> " + dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date)))

if(last_worklog.getTimeSpent()>1 && dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date))){
log.error("inside if block");
String comment=last_logged+'sec logged by '+author+' on date '+last_worklog_date
log.error("comment -> "+ comment)
log.error("last_worklog.getId() -> "+ last_worklog.getId())
def worklog = new WorklogImpl2(issue, last_worklog.getId(), author, comment, new Date(), null, null,last_logged, UsersRole)
worklogManager.update(issue.reporter, worklog, 0L, true)
} else {
log.error("else block");
}

@Sadaf Jabin 

As per your guidelines and support. I able to restrict the user to log hours for the Future date with the below working code.

import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.component.pico.ComponentManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import java.lang.Object
import com.atlassian.jira.issue.worklog.WorklogImpl2
import java.text.SimpleDateFormat
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.worklog.DefaultWorklogManager
import com.atlassian.jira.security.roles.ProjectRoleManager
import com.atlassian.jira.issue.worklog.Worklog
import com.atlassian.jira.datetime.LocalDate
import com.atlassian.jira.issue.worklog.*

def issueManager = ComponentAccessor.getIssueManager()
def user= ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
MutableIssue issue = event.issue as MutableIssue
WorklogManager worklogManager = ComponentAccessor.getWorklogManager()
List worklogs = worklogManager.getByIssue(issue)
def last_worklog=worklogs.last()
def author = last_worklog.getAuthorKey()
def dateformat= new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
def UsersRole = projectRoleManager.getProjectRole("Users")
long timespent = 1
def last_logged=last_worklog.getTimeSpent()
log.error("last_logged -> " + last_logged);
Calendar cal = Calendar.getInstance();
//cal.add(Calendar.DATE, -30);
Date todate1 = cal.getTime();
def date_limit = dateformat.format(todate1);
log.error("date_limit -> "+date_limit)
def last_worklog_date=dateformat.format(last_worklog.getStartDate())
log.error("last_worklog_date -> "+last_worklog_date)
log.error(dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date)))

if(last_worklog.getTimeSpent()>1 && dateformat.parse(date_limit).before(dateformat.parse(last_worklog_date))){
String comment=last_logged+'sec logged by '+author+' on date '+last_worklog_date
def worklog = new WorklogImpl2(issue, last_worklog.getId(), author, comment, new Date(), null, null,last_logged, UsersRole)
worklogManager.delete(user, worklog, null, true);
}

 

Now, I would like to avoid making entries in the remaining hours, if user try to enter hrs for the future dates.

Remaining_hrs.jpg

Hi Sadaf Jabin,

Did you get any solution from the users or still waiting for the inputs, actually i too want to implement the same and i would like to know how and where we need to implement the logic to validate the work log "Date Started " field in the work log screen 

@mvinodPlease refer to the first answer. I was able to acheive the restriction using the shared script.

Thanks for your reply , Sadaf Jabin!

To implement the code , i have navigated to the "Create Listeners" screen under Script Runner. (Listeners -> Create -> Create Listeners).

Now, i am not aware where do we need to place the code and how to debug the code to validate the Date Started  value from the Log Work screen.Script_Listneres.JPG

Hi @ Sadaf Jabin /  @Swarna_Radha ,

I have created a new Custom listener and placed the script code which was shared by Sadaf_Jabin  on Nov 07, 2019. 

PFA screen shoots for the reference.

Now, am not hot to cross check whether the script is running or not (or) do we need to do any other option to make it work. Since in the screen shots it says it was not yet executed in the Execution history column. 

Also kindly let me know, where do we need to view the error log details after the execution of the code.

 

Future_Date_LogWork.jpg

@mvinodKindly update the project for which you want this feature enabled. As we can see from the screenshot, it is not associated with any project yet.

Hi Sadaf,

I have removed the project name purposely using MS paint but it is mapped to a project. Let's say it is mapped to Project A.

@mvinodIn that case try logging work for the month of April. It will auto update the date to todays date

Hi Sadaf,

did you considered to use some plugin? I think the Tempo Timesheets plugin should be able to disable logging of work for previous month.

Best regards,

Ondřej

Hi Ondřej,

Thanks for your response.

I am actually looking for a solution without having to involve additional plugins. It would be great if you could suggest in that line.

Thanks,

Sadaf Jabin

Tempo doesn't solve this issue

Like BC likes this

Suggest an answer

Log in or Sign up to answer
TAGS

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you