Refactor document_matches_workflow method

This commit is contained in:
shamoon 2023-12-30 21:49:54 -08:00
parent 8f0565a936
commit 7ccfa45eb9

View File

@ -245,150 +245,182 @@ def _split_match(matching_model):
]
def consumable_document_matches_workflow(
document: ConsumableDocument,
trigger: WorkflowTrigger,
) -> tuple[bool, str]:
"""
Returns True if the ConsumableDocument matches all filters from the workflow trigger,
False otherwise. Includes a reason if doesn't match
"""
trigger_matched = True
reason = ""
# Document source vs trigger source
if document.source not in [int(x) for x in list(trigger.sources)]:
reason = (
f"Document source {document.source.name} not in"
f" {[DocumentSource(int(x)).name for x in trigger.sources]}",
)
trigger_matched = False
# Document mail rule vs trigger mail rule
if (
document.mailrule_id is not None
and trigger.filter_mailrule is not None
and document.mailrule_id != trigger.filter_mailrule.pk
):
reason = (
f"Document mail rule {document.mailrule_id}"
f" != {trigger.filter_mailrule.pk}",
)
trigger_matched = False
# Document filename vs trigger filename
if (
trigger.filter_filename is not None
and len(trigger.filter_filename) > 0
and not fnmatch(
document.original_file.name.lower(),
trigger.filter_filename.lower(),
)
):
reason = (
f"Document filename {document.original_file.name} does not match"
f" {trigger.filter_filename.lower()}",
)
trigger_matched = False
# Document path vs trigger path
if (
trigger.filter_path is not None
and len(trigger.filter_path) > 0
and not document.original_file.match(trigger.filter_path)
):
reason = (
f"Document path {document.original_file}"
f" does not match {trigger.filter_path}",
)
trigger_matched = False
return (trigger_matched, reason)
def existing_document_matches_workflow(
document: Document,
trigger: WorkflowTrigger,
) -> tuple[bool, str]:
"""
Returns True if the Document matches all filters from the workflow trigger,
False otherwise. Includes a reason if doesn't match
"""
trigger_matched = True
reason = ""
if trigger.matching_algorithm > MatchingModel.MATCH_NONE and not matches(
trigger,
document,
):
reason = (
f"Document content matching settings for algorithm '{trigger.matching_algorithm}' did not match",
)
trigger_matched = False
# Document tags vs trigger has_tags
if (
trigger.filter_has_tags.all().count() > 0
and document.tags.filter(
id__in=trigger.filter_has_tags.all().values_list("id"),
).count()
== 0
):
reason = (
f"Document tags {document.tags.all()} do not include"
f" {trigger.filter_has_tags.all()}",
)
trigger_matched = False
# Document correpondent vs trigger has_correspondent
if (
trigger.filter_has_correspondent is not None
and document.correspondent != trigger.filter_has_correspondent
):
reason = (
f"Document correspondent {document.correspondent} does not match {trigger.filter_has_correspondent}",
)
trigger_matched = False
# Document document_type vs trigger has_document_type
if (
trigger.filter_has_document_type is not None
and document.document_type != trigger.filter_has_document_type
):
reason = (
f"Document doc type {document.document_type} does not match {trigger.filter_has_document_type}",
)
trigger_matched = False
# Document original_filename vs trigger filename
if (
trigger.filter_filename is not None
and len(trigger.filter_filename) > 0
and document.original_filename is not None
and not fnmatch(
document.original_filename.lower(),
trigger.filter_filename.lower(),
)
):
reason = (
f"Document filename {document.original_filename} does not match"
f" {trigger.filter_filename.lower()}",
)
trigger_matched = False
return (trigger_matched, reason)
def document_matches_workflow(
document: Union[ConsumableDocument, Document],
workflow: Workflow,
trigger_type: WorkflowTrigger.WorkflowTriggerType,
) -> bool:
"""
Returns True if the incoming document matches all filters and
Returns True if the ConsumableDocument or Document matches all filters and
settings from the workflow trigger, False otherwise
"""
def log_match_failure(reason: str):
logger.info(f"Document did not match {workflow}")
logger.debug(reason)
trigger_matched = True
if workflow.triggers.filter(type=trigger_type).count() == 0:
trigger_matched = False
log_match_failure(
f"No matching triggers with type {trigger_type} found",
)
logger.info(f"Document did not match {workflow}")
logger.debug(f"No matching triggers with type {trigger_type} found")
else:
triggers = workflow.triggers.filter(type=trigger_type)
for trigger in triggers:
for trigger in workflow.triggers.filter(type=trigger_type):
if trigger_type is WorkflowTrigger.WorkflowTriggerType.CONSUMPTION:
# document is type ConsumableDocument
# Document source vs template source
if document.source not in [int(x) for x in list(trigger.sources)]:
log_match_failure(
f"Document source {document.source.name} not in"
f" {[DocumentSource(int(x)).name for x in trigger.sources]}",
)
trigger_matched = False
# Document mail rule vs template mail rule
if (
document.mailrule_id is not None
and trigger.filter_mailrule is not None
and document.mailrule_id != trigger.filter_mailrule.pk
):
log_match_failure(
f"Document mail rule {document.mailrule_id}"
f" != {trigger.filter_mailrule.pk}",
)
trigger_matched = False
# Document filename vs template filename
if (
trigger.filter_filename is not None
and len(trigger.filter_filename) > 0
and not fnmatch(
document.original_file.name.lower(),
trigger.filter_filename.lower(),
)
):
log_match_failure(
f"Document filename {document.original_file.name} does not match"
f" {trigger.filter_filename.lower()}",
)
trigger_matched = False
# Document path vs template path
if (
trigger.filter_path is not None
and len(trigger.filter_path) > 0
and not document.original_file.match(trigger.filter_path)
):
log_match_failure(
f"Document path {document.original_file}"
f" does not match {trigger.filter_path}",
)
trigger_matched = False
trigger_matched, reason = consumable_document_matches_workflow(
document,
trigger,
)
elif (
trigger_type is WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED
or trigger_type is WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED
):
# document is type Document
if (
trigger.matching_algorithm > MatchingModel.MATCH_NONE
and not matches(trigger, document)
):
log_match_failure(
f"Document content matching settings for algorithm '{trigger.matching_algorithm}' did not match",
)
trigger_matched = False
# Document has_tags vs document tags
if (
trigger.filter_has_tags.all().count() > 0
and document.tags.filter(
id__in=trigger.filter_has_tags.all().values_list("id"),
).count()
== 0
):
log_match_failure(
f"Document tags {document.tags.all()} do not include"
f" {trigger.filter_has_tags.all()}",
)
trigger_matched = False
# Document has_correspondent vs document correpondent
if (
trigger.filter_has_correspondent is not None
and document.correspondent != trigger.filter_has_correspondent
):
log_match_failure(
f"Document correspondent {document.correspondent} does not match {trigger.filter_has_correspondent}",
)
trigger_matched = False
# Document has_correspondent vs document correpondent
if (
trigger.filter_has_document_type is not None
and document.document_type != trigger.filter_has_document_type
):
log_match_failure(
f"Document doc type {document.document_type} does not match {trigger.filter_has_document_type}",
)
trigger_matched = False
# Document filename vs template filename
if (
trigger.filter_filename is not None
and len(trigger.filter_filename) > 0
and document.original_filename is not None
and not fnmatch(
document.original_filename.lower(),
trigger.filter_filename.lower(),
)
):
log_match_failure(
f"Document filename {document.original_filename} does not match"
f" {trigger.filter_filename.lower()}",
)
trigger_matched = False
trigger_matched, reason = existing_document_matches_workflow(
document,
trigger,
)
else:
# New trigger types need to be checked above
# New trigger types need to be explicitly checked above
raise Exception(f"Trigger type {trigger_type} not yet supported")
if trigger_matched:
logger.info(f"Document matched {trigger} from {workflow}")
# matched, bail early
return True
else:
logger.info(f"Document did not match {workflow}")
logger.debug(reason)
return trigger_matched