cr-connect-workflow/crc/scripts/request_review.py
Dan Funk d39ef658a2 Made some modifications to the Approval so that it knows exactly what versions of every file are being sent for approval
Added the following columns:
  * date_created - so we know when the file was created
  * renamed workflow_version to just "version", because everything has a version,  this is the version of the request.
  * workflow_hash - this is just a quick way to see what files and versions are associated with the request, it could be factored out.
  * study - a quick relationship link to the study, so that this model is easier to use.
  * workflow - ditto
  * approval_files - these is a list from a new link table that links an approval to specific files and versions.

The RequestApproval is logically sound, but still needs some additional pieces in place to be callable from a BPMN workflow diagram.

Altered the file service to pick up on changes to files vs adding new files, so that versions are picked up correctly as
users modify their submission - adding new files or replacing existing ones.  Deleting files worries me, and I will need to revisit this.

The damn base test keeps giving me a headache, so I made changes there to see if clearing and dropping the database each time won't allow the tests to pass more consistently.

Lots more tests around the file service to make sure it is versioning user uploaded files correctly.

The "Test Request Approval Script" tries to find to assure the correct behavior as this is likely to be called many times repeatedly and with little knowledge of the internal system.  So it should just "do the right thing".
2020-05-23 15:08:17 -04:00

72 lines
3.4 KiB
Python

from datetime import datetime
from sqlalchemy import desc
from crc import db
from crc.models.approval import ApprovalModel, ApprovalStatus, ApprovalFile
from crc.scripts.script import Script
from crc.services.file_service import FileService
class RequestApproval(Script):
"""This still needs to be fully wired up as a Script task callable from the workflow
But the basic logic is here just to get the tests passing and logic sound. """
def get_description(self):
return "Creates an approval request on this workflow, by the given approver_uid"
def add_approval(self, study_id, workflow_id, approver_uid):
"""we might have multiple approvals for a workflow, so I would expect this
method to get called many times."""
# Find any existing approvals for this workflow and approver.
latest_approval_request = db.session.query(ApprovalModel).\
filter(ApprovalModel.workflow_id == workflow_id). \
filter(ApprovalModel.approver_uid == approver_uid). \
order_by(desc(ApprovalModel.version)).first()
# Construct as hash of the latest files to see if things have changed since
# the last approval.
latest_files = FileService.get_workflow_files(workflow_id)
current_workflow_hash = self.generate_workflow_hash(latest_files)
# If an existing approval request exists and no changes were made, do nothing.
# If there is an existing approval request for a previous version of the workflow
# then add a new request, and cancel any waiting/pending requests.
if latest_approval_request:
# We could just compare the ApprovalFile lists here and do away with this hash.
if latest_approval_request.workflow_hash == current_workflow_hash:
return # This approval already exists.
else:
latest_approval_request.status = ApprovalStatus.CANCELED.value
db.session.add(latest_approval_request)
version = latest_approval_request.version + 1
else:
version = 1
model = ApprovalModel(study_id=study_id, workflow_id=workflow_id,
approver_uid=approver_uid, status=ApprovalStatus.WAITING.value,
message="", date_created=datetime.now(),
version=version, workflow_hash=current_workflow_hash)
approval_files = self.create_approval_files(latest_files, model)
db.session.add(model)
db.session.add_all(approval_files)
db.session.commit()
def create_approval_files(self, files, approval):
"""Currently based exclusively on the status of files associated with a workflow."""
file_approval_models = []
for file in files:
file_approval_models.append(ApprovalFile(file_id=file.id,
approval=approval,
file_version=file.latest_version))
return file_approval_models
def generate_workflow_hash(self, files):
"""Currently based exclusively on the status of files associated with a workflow."""
version_array = []
for file in files:
version_array.append(str(file.id) + "[" + str(file.latest_version) + "]")
full_version = "-".join(version_array)
return full_version