Days since Task Completed

Questions about and code samples for automation process code snippets within Select.
Post Reply
B_Hinote
Posts: 57
Joined: Tue Jan 08, 2019 7:20 pm

Days since Task Completed

Post by B_Hinote »

I have a situation where I need to add a Task based on several conditions, but one of them is that a specific task was completed over 14 days prior.
I am not clear on the correct method to determine the number of days since between the dates as the following code is not working.

Do you have any suggestions?

Code: Select all

from System import *
from SoftPro.ClientModel import *
from SoftPro.Select.Client import *
from SoftPro.OrderTracking.Client.Orders import *
from System import DateTime *

def TaskCompletedOver14Days():
	over14Days = False
	# If PmtOvr14 Task already exists Return False, otherwise go the the next test
	if any(task.Code.lower() == 'pmtovr14' for task in Context.ChecklistTasks):
		return False

	# Check to see if Conditioning Task Exits, Has been Completed and Is over 14 Days Old,  If not Return False
	if any((task.Code.lower() == 'revdlvrpol' and task.Status == TaskStatusType.Completed) for task in Context.ChecklistTasks):
		today = DateTime.Today 
		If abs(today-task.CompletedDate).days > 14:
			over14Days = True
	
	if over14Days == False:
		return False

	return True

TaskCompletedOver14Days()
Thank you.
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Days since Task Completed

Post by BobRichards »

Yes I do. But what error messages are you getting (if any)? Have you tried coding it as a Custom Order Rule (COR) so you can inspect the values of the code variables to debug it. I suspect the code never goes into the body of the second "if" or it would have detected errors on line 16.

My recommendation is:
  • If you have privilege, start all automation scripts as Custom Order Rules in the COR environment since it is much friendlier for debugging errors. When it is as close as practical, copy it to automation and make necessary changes. (Such as change the context,...)
  • Try to limit the scope of where the errors might be occurring. Can you tell what is working so we can rule out part of the script? For instance, in the body of the first "if" statement, try setting an order property to the current time so you can test it.

    Code: Select all

        if any(task.Code.lower() == 'pmtovr14' for task in Context.ChecklistTasks):
            Context.RelatedOrders = DateTime.Now
            return False
  • Post any error messages you get when the code fails.
Also...

Code: Select all

    return over14Days
...is logically the same as...

Code: Select all

    if over14Days == False:
        return False

    return True
...and clearer.
Bob Richards, Senior Software Developer, SoftPro
B_Hinote
Posts: 57
Joined: Tue Jan 08, 2019 7:20 pm

Re: Days since Task Completed

Post by B_Hinote »

Thanks for the suggestions.
I have been able to get the code to work down to the point of determining the number of days between the Task Completed Date and Today.

Code: Select all

def Order_RelatedOrders_Value(args):
	over14Days = False
	# If Task already exists Return False, otherwise go the the next test
	if any(task.Code.lower() == 'pmtovr14' for task in args.Context.Root.ChecklistTasks):
		return #False

	# If Task already exists Return False, otherwise go the the next test
	for task in args.Context.Root.ChecklistTasks:
		#if any((task.Code.lower() == 'revdlvrpol' and task.Status == TaskStatusType.Completed) for task in args.Context.Root.ChecklistTasks):
		if (task.Code.lower() == 'revdlvrpol' and task.Status == TaskStatusType.Completed):
			today = DateTime.Now
			If abs(today - task.CompletedDate).days > 14:
				over14Days = True
				#args.Value = str(test)
				return # over14Days
Please see the attached image identifying the errors.

It appears that our Python Version does not like the abs() function or the ".days" option.
Any thoughts on how to get the number of days?

Thank you
Attachments
Python_Errors.jpg
Python_Errors.jpg (214.16 KiB) Viewed 2230 times
B_Hinote
Posts: 57
Joined: Tue Jan 08, 2019 7:20 pm

Re: Days since Task Completed

Post by B_Hinote »

Although I am trying to create an Automation Snippet, as you suggested I have been working with a COR to prove out the code first.

I was finally able to create the following code that produces the result I am after, but it contains hardcoded dates because everything I have tried for setting the variables "today" and "completedDate" to the values I am trying to use have resulted in Errors causing the code to no longer work.

Code: Select all

from System import *
from SoftPro.ClientModel import *
from SoftPro.OrderTracking.Client import *
from SoftPro.OrderTracking.Client.Orders import *
#from datetime import datetime
import datetime

def Order_RelatedOrders_Value(args):
	over14Days = False
	# If Task already exists Return False, otherwise go the the next test
	if any(task.Code.lower() == 'pmtovr14' for task in args.Context.Root.ChecklistTasks):
		return #False

	for task in args.Context.Root.ChecklistTasks:
		#if any((task.Code.lower() == 'revdlvrpol' and task.Status == TaskStatusType.Completed) for task in args.Context.Root.ChecklistTasks):
		if (task.Code.lower() == 'revdlvrpol' and task.Status == TaskStatusType.Completed):
			today = datetime.datetime(2019, 8, 15)		#Value I want to user: DateTime.Now
			completedDate = datetime.datetime(2019, 7, 31)	#Value I want to user: task.CompletedDate
			duration = today - completedDate
			if duration.days > 14:
				args.Value = str(duration.days)
				over14Days = True
	
	return over14Days	
If I replace either of the "datetime.datetime()" hardcoded values with either of the fields to the right, I get the lowing error at the application level.
"Error encountered during rule execution. unsupported operand type(s) for -: 'DateTime" and "datetime'"

In order for me to use "duration.days" to produce the number of days between the two dates, the "duration" variable must be of type "datetime".

Any ideas on how to resolve this?

Thank you.
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Days since Task Completed

Post by BobRichards »

I believe the problems you were having were having relates to combining Python libraries and .NET ones. I prefer to stay with the .NET ones since I am more familiar with them - but both are fine if you stay consistent. You were very close to working code.

Code: Select all

	# Exit if there are no tasks in order.
	checklistTasks = args.Context.Root.ChecklistTasks
	if not checklistTasks:
		args.Value = str('No checklist tasks')
		return over14Days
	
	# Exit if ANY task has the Code of 'pmtovr14'.
	if any((task.Code is not None and task.Code.lower()) == 'pmtovr14' for task in checklistTasks):
		args.Value = str('Found task code: pmtovr14')
		return str(over14Days)
The first section says if there are no checklist tasks, then exit now. This makes the COR faster and the UI more responsive. The second section makes sure the task.Code is specified before trying to convert it to lower case. If Code is None (empty), you can't call "tolower()" on it. We need to do that any time a string might not be set.

The entire snippet is below:

Code: Select all

from System import *
from SoftPro.ClientModel import *
from SoftPro.OrderTracking.Client import *
from SoftPro.OrderTracking.Client.Orders import *

def Order_RelatedOrders_Value(args):
	over14Days = False
	
	# Exit if there are no tasks in order.
	checklistTasks = args.Context.Root.ChecklistTasks
	if not checklistTasks:
		args.Value = str('No checklist tasks')
		return over14Days
	
	# Exit if ANY task has the Code of 'pmtovr14'.
	if any((task.Code is not None and task.Code.lower()) == 'pmtovr14' for task in checklistTasks):
		args.Value = str('Found task code: pmtovr14')
		return str(over14Days)

	# Found task(s) that need work.
	for task in checklistTasks:
		if (task.Code is not None
				and task.Code.lower() == 'revdlvrpol' 
				and task.Status == TaskStatusType.Completed):
			today = DateTime.Now
			completedDate = task.CompletedDate
			duration = today - completedDate  # Add/Subtraction of dates creates a .NET TimeSpan object.
			if duration.Days > 14:
				args.Value = 'Day: ' + str(duration.Days)
				over14Days = True
	
	args.Value = 'Exit: ' + str(over14Days)
	return str(over14Days)
Notice that I removed the Python date library and am using the .NET version System.DateTime that is imported in the first line of the snippet. When two DateTime objects are added or subtracted, a System.TimeSpan is created to hold the new value. The classes have lots of properties and methods (functions) that are really useful.

As additional debugging help, I often return a string to the COR value so I can see how far in the code I got with unique strings to verify logic. Test drive the code and see if it helps.
Bob Richards, Senior Software Developer, SoftPro
B_Hinote
Posts: 57
Joined: Tue Jan 08, 2019 7:20 pm

Re: Days since Task Completed

Post by B_Hinote »

Great information and advice.

I could have sworn that before I started importing "datetime" or any other libraries, that I tried setting both variables as you have them now and was receiving an error indicating that ".Days" was not defined for a "datetime" field or something like that. Obviously, I must have had something else wrong or causing me grief. :-)

Anyway, this works exactly as I need it to and I greatly appreciate your instruction/advice on the additional conditions for qualifying and exiting the code as quickly as possible. This makes perfect sense.

Thanks again.

Brian
Post Reply