Adding some additional logic to the approval endpoint so that we take related approvals into account when setting the status. In addtion to prevous status options, there is a new status of "AWAITING" which means there are pending approvals before this approval that still need to be approved or canceled.

This commit is contained in:
Dan Funk 2020-06-05 14:33:00 -04:00
parent b6abb0cbe2
commit f0db5b70fc
5 changed files with 39 additions and 3 deletions

View File

@ -814,6 +814,12 @@ paths:
description: If set to true, returns all the approvals known to the system.
schema:
type: boolean
- name: as_user
in: query
required: false
description: If provided, returns the approval results as they would appear for that user.
schema:
type: string
get:
operationId: crc.api.approval.get_approvals
summary: Provides a list of workflows approvals

View File

@ -13,9 +13,11 @@ from crc.services.approval_service import ApprovalService
from crc.services.ldap_service import LdapService
def get_approvals(everything=False):
def get_approvals(everything=False, as_user=None):
if everything:
approvals = ApprovalService.get_all_approvals(include_cancelled=True)
elif as_user:
approvals = ApprovalService.get_all_approvals(as_user, include_cancelled=False)
else:
approvals = ApprovalService.get_approvals_per_user(g.user.uid, include_cancelled=False)
results = ApprovalSchema(many=True).dump(approvals)

View File

@ -20,6 +20,9 @@ class ApprovalStatus(enum.Enum):
DECLINED = "DECLINED" # rejected by the reviewer
CANCELED = "CANCELED" # The document was replaced with a new version and this review is no longer needed.
# Used for overall status only, never set on a task.
AWAITING = "AWAITING" # awaiting another approval
class ApprovalFile(db.Model):
file_data_id = db.Column(db.Integer, db.ForeignKey(FileDataModel.id), primary_key=True)

View File

@ -11,7 +11,8 @@ class RequestApproval(Script):
return """
Creates an approval request on this workflow, by the given approver_uid(s),"
Takes multiple arguments, which should point to data located in current task
or be quoted strings.
or be quoted strings. The order is important. Approvals will be processed
in this order.
Example:
RequestApproval approver1 "dhf8r"

View File

@ -27,19 +27,43 @@ class ApprovalService(object):
if not include_cancelled:
query=query.filter(ApprovalModel.status != ApprovalStatus.CANCELED.value)
approvals = query.all()
approvals = query.all() ## all non-cancelled approvals.
study_approval_status = ""
# IF THIS IS RELATED TO THE CURRENT USER
for approval_model in approvals:
if approval_model.approver_uid == approver_uid:
main_approval = Approval.from_model(approval_model)
else:
related_approvals.append(Approval.from_model(approval_model))
# IF WE ARE JUST RETURNING ALL OF THE APPROVALS PER STUDY
if not main_approval and len(related_approvals) > 0:
main_approval = related_approvals[0]
related_approvals = related_approvals[1:]
if(main_approval): # May be null if the study has no approvals.
main_approval.status = ApprovalService.__calculate_overall_approval_status(main_approval)
if len(related_approvals) > 0:
main_approval.related_approvals = related_approvals
return main_approval
@staticmethod
def __calculate_overall_approval_status(approval):
# In the case of pending approvals, check to see if there is a related approval
# that proceeds this approval - and if it is declined, or still pending, then change
# the state of the approval to be Delcined, or Waiting respectively.
if approval.status == ApprovalStatus.PENDING.value:
for ra in approval.related_approvals:
if ra.id < approval.id:
if ra.status == ApprovalStatus.DECLINED.value or ra.status == ApprovalStatus.CANCELED.value:
return ra.status # If any prior approval id declined or cancelled so is this approval.
elif ra.status == ApprovalStatus.PENDING.value:
return ApprovalStatus.AWAITING.value # if any prior approval is pending, then this is waiting.
else:
return approval.status
@staticmethod
def get_approvals_per_user(approver_uid, include_cancelled=False):
"""Returns a list of approval objects (not db models) for the given