224 lines
11 KiB
Python
224 lines
11 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
|
# All rights reserved.
|
|
"""
|
|
Trustee document workflow method: extract from files, process to positions, sync to accounting.
|
|
"""
|
|
|
|
import logging
|
|
from modules.workflows.methods.methodBase import MethodBase
|
|
from modules.datamodels.datamodelWorkflowActions import WorkflowActionDefinition, WorkflowActionParameter
|
|
from modules.shared.frontendTypes import FrontendType
|
|
|
|
from .actions.extractFromFiles import extractFromFiles
|
|
from .actions.processDocuments import processDocuments
|
|
from .actions.syncToAccounting import syncToAccounting
|
|
from .actions.refreshAccountingData import refreshAccountingData
|
|
from .actions.queryData import queryData
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MethodTrustee(MethodBase):
|
|
"""Trustee document and expense workflow: extract, process, sync to accounting."""
|
|
|
|
def __init__(self, services):
|
|
super().__init__(services)
|
|
self.name = "trustee"
|
|
self.description = "Trustee document extraction, processing and accounting sync"
|
|
|
|
self._actions = {
|
|
"extractFromFiles": WorkflowActionDefinition(
|
|
actionId="trustee.extractFromFiles",
|
|
description="Extract document type and data from PDF/JPG (fileIds or SharePoint folder)",
|
|
dynamicMode=False,
|
|
parameters={
|
|
"fileIds": WorkflowActionParameter(
|
|
name="fileIds",
|
|
type="list",
|
|
frontendType=FrontendType.JSON,
|
|
required=False,
|
|
description="List of file IDs already in DB (alternative to connectionReference + sharepointFolder)",
|
|
),
|
|
"connectionReference": WorkflowActionParameter(
|
|
name="connectionReference",
|
|
type="str",
|
|
frontendType=FrontendType.USER_CONNECTION,
|
|
required=False,
|
|
description="Microsoft connection for SharePoint (use with sharepointFolder)",
|
|
),
|
|
"sharepointFolder": WorkflowActionParameter(
|
|
name="sharepointFolder",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="SharePoint folder path (e.g. /sites/MySite/Documents/Expenses)",
|
|
),
|
|
"featureInstanceId": WorkflowActionParameter(
|
|
name="featureInstanceId",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Trustee feature instance ID",
|
|
),
|
|
"prompt": WorkflowActionParameter(
|
|
name="prompt",
|
|
type="str",
|
|
frontendType=FrontendType.TEXTAREA,
|
|
required=False,
|
|
description="AI prompt for extraction (optional)",
|
|
),
|
|
},
|
|
execute=extractFromFiles.__get__(self, self.__class__),
|
|
),
|
|
"processDocuments": WorkflowActionDefinition(
|
|
actionId="trustee.processDocuments",
|
|
description="Create TrusteeDocument + TrusteePosition from extraction result (documentList from previous action)",
|
|
dynamicMode=False,
|
|
parameters={
|
|
"documentList": WorkflowActionParameter(
|
|
name="documentList",
|
|
type="list",
|
|
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
|
required=True,
|
|
description="Reference to extractFromFiles result (e.g. docList:messageId:extract_result)",
|
|
),
|
|
"featureInstanceId": WorkflowActionParameter(
|
|
name="featureInstanceId",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Trustee feature instance ID",
|
|
),
|
|
},
|
|
execute=processDocuments.__get__(self, self.__class__),
|
|
),
|
|
"syncToAccounting": WorkflowActionDefinition(
|
|
actionId="trustee.syncToAccounting",
|
|
description="Push trustee positions to accounting (documentList = processDocuments result)",
|
|
dynamicMode=False,
|
|
parameters={
|
|
"documentList": WorkflowActionParameter(
|
|
name="documentList",
|
|
type="list",
|
|
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
|
required=True,
|
|
description="Reference to processDocuments result message",
|
|
),
|
|
"featureInstanceId": WorkflowActionParameter(
|
|
name="featureInstanceId",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Trustee feature instance ID",
|
|
),
|
|
},
|
|
execute=syncToAccounting.__get__(self, self.__class__),
|
|
),
|
|
"refreshAccountingData": WorkflowActionDefinition(
|
|
actionId="trustee.refreshAccountingData",
|
|
description="Import/refresh accounting data from external system (e.g. Abacus) into local tables. Checks cache freshness; use forceRefresh to re-import.",
|
|
dynamicMode=True,
|
|
parameters={
|
|
"featureInstanceId": WorkflowActionParameter(
|
|
name="featureInstanceId",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Trustee feature instance ID",
|
|
),
|
|
"forceRefresh": WorkflowActionParameter(
|
|
name="forceRefresh",
|
|
type="bool",
|
|
frontendType=FrontendType.CHECKBOX,
|
|
required=False,
|
|
description="Force re-import even if data is fresh (default: false)",
|
|
),
|
|
"dateFrom": WorkflowActionParameter(
|
|
name="dateFrom",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="Start date filter for journal entries (YYYY-MM-DD)",
|
|
),
|
|
"dateTo": WorkflowActionParameter(
|
|
name="dateTo",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="End date filter for journal entries (YYYY-MM-DD)",
|
|
),
|
|
},
|
|
execute=refreshAccountingData.__get__(self, self.__class__),
|
|
),
|
|
"queryData": WorkflowActionDefinition(
|
|
actionId="trustee.queryData",
|
|
description="Read data from the Trustee DB (lookup tenant+rent, raw recordset, or aggregate). Does NOT trigger an external sync.",
|
|
dynamicMode=False,
|
|
parameters={
|
|
"featureInstanceId": WorkflowActionParameter(
|
|
name="featureInstanceId",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Trustee feature instance ID",
|
|
),
|
|
"mode": WorkflowActionParameter(
|
|
name="mode",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Query mode: lookup | raw | aggregate",
|
|
),
|
|
"entity": WorkflowActionParameter(
|
|
name="entity",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=True,
|
|
description="Entity to query: tenantWithRent | contact | journalLines | accounts | balances",
|
|
),
|
|
"tenantNameRef": WorkflowActionParameter(
|
|
name="tenantNameRef",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="Tenant name to match (or {{wire.field}} placeholder)",
|
|
),
|
|
"tenantAddressRef": WorkflowActionParameter(
|
|
name="tenantAddressRef",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="Tenant address to match (tolerant)",
|
|
),
|
|
"period": WorkflowActionParameter(
|
|
name="period",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="Period filter: YYYY or YYYY-MM-DD/YYYY-MM-DD",
|
|
),
|
|
"rentAccountPattern": WorkflowActionParameter(
|
|
name="rentAccountPattern",
|
|
type="str",
|
|
frontendType=FrontendType.TEXT,
|
|
required=False,
|
|
description="Account-number pattern for rent revenue (e.g. '6000-6099' or '6*')",
|
|
),
|
|
"filterJson": WorkflowActionParameter(
|
|
name="filterJson",
|
|
type="str",
|
|
frontendType=FrontendType.TEXTAREA,
|
|
required=False,
|
|
description="Optional JSON filter for mode=raw/aggregate",
|
|
),
|
|
},
|
|
execute=queryData.__get__(self, self.__class__),
|
|
),
|
|
}
|
|
self._validateActions()
|
|
|
|
self.extractFromFiles = extractFromFiles.__get__(self, self.__class__)
|
|
self.processDocuments = processDocuments.__get__(self, self.__class__)
|
|
self.syncToAccounting = syncToAccounting.__get__(self, self.__class__)
|
|
self.refreshAccountingData = refreshAccountingData.__get__(self, self.__class__)
|
|
self.queryData = queryData.__get__(self, self.__class__)
|