automation fixes
This commit is contained in:
parent
ebc4b2a080
commit
06e68c343b
17 changed files with 207 additions and 85 deletions
2
app.py
2
app.py
|
|
@ -501,6 +501,8 @@ async def lifespan(app: FastAPI):
|
||||||
return
|
return
|
||||||
if isinstance(exc, ConnectionAbortedError):
|
if isinstance(exc, ConnectionAbortedError):
|
||||||
return
|
return
|
||||||
|
if exc and "LocalProtocolError" in type(exc).__name__:
|
||||||
|
return
|
||||||
loop.default_exception_handler(ctx)
|
loop.default_exception_handler(ctx)
|
||||||
main_loop.set_exception_handler(_suppressClientDisconnect)
|
main_loop.set_exception_handler(_suppressClientDisconnect)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
|
|
||||||
|
|
@ -150,52 +150,21 @@ NAVIGATION_SECTIONS = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
# --- Workflow-Automation (System-Komponente, cross-mandate) ---
|
# --- Solution Design (System-Komponente, cross-mandate) ---
|
||||||
|
# Single nav entry; tabs are managed internally by WorkflowAutomationHubPage.
|
||||||
{
|
{
|
||||||
"id": "workflowAutomation",
|
"id": "workflowAutomation",
|
||||||
"title": t("Workflow-Automation"),
|
"title": t("Lösungsdesign"),
|
||||||
"order": 25,
|
"order": 25,
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "wa-workflows",
|
"id": "wa-hub",
|
||||||
"objectKey": "ui.system.workflowAutomation.workflows",
|
"objectKey": "ui.system.workflowAutomation",
|
||||||
"label": t("Workflows"),
|
"label": t("Workflow-Automation"),
|
||||||
"icon": "FaSitemap",
|
"icon": "FaSitemap",
|
||||||
"path": "/workflow-automation?tab=workflows",
|
"path": "/workflow-automation",
|
||||||
"order": 10,
|
"order": 10,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "wa-editor",
|
|
||||||
"objectKey": "ui.system.workflowAutomation.editor",
|
|
||||||
"label": t("Editor"),
|
|
||||||
"icon": "FaProjectDiagram",
|
|
||||||
"path": "/workflow-automation?tab=editor",
|
|
||||||
"order": 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "wa-templates",
|
|
||||||
"objectKey": "ui.system.workflowAutomation.templates",
|
|
||||||
"label": t("Vorlagen"),
|
|
||||||
"icon": "FaCopy",
|
|
||||||
"path": "/workflow-automation?tab=templates",
|
|
||||||
"order": 30,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "wa-runs",
|
|
||||||
"objectKey": "ui.system.workflowAutomation.runs",
|
|
||||||
"label": t("Läufe"),
|
|
||||||
"icon": "FaPlay",
|
|
||||||
"path": "/workflow-automation?tab=runs",
|
|
||||||
"order": 40,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "wa-tasks",
|
|
||||||
"objectKey": "ui.system.workflowAutomation.tasks",
|
|
||||||
"label": t("Tasks"),
|
|
||||||
"icon": "FaTasks",
|
|
||||||
"path": "/workflow-automation?tab=tasks",
|
|
||||||
"order": 50,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
# --- Administration (with subgroups) ---
|
# --- Administration (with subgroups) ---
|
||||||
|
|
@ -237,7 +206,7 @@ NAVIGATION_SECTIONS = [
|
||||||
{
|
{
|
||||||
"id": "admin-users",
|
"id": "admin-users",
|
||||||
"objectKey": "ui.admin.users",
|
"objectKey": "ui.admin.users",
|
||||||
"label": t("Benutzer"),
|
"label": t("Übersicht"),
|
||||||
"icon": "FaUsers",
|
"icon": "FaUsers",
|
||||||
"path": "/admin/users",
|
"path": "/admin/users",
|
||||||
"order": 10,
|
"order": 10,
|
||||||
|
|
@ -246,7 +215,7 @@ NAVIGATION_SECTIONS = [
|
||||||
{
|
{
|
||||||
"id": "admin-invitations",
|
"id": "admin-invitations",
|
||||||
"objectKey": "ui.admin.invitations",
|
"objectKey": "ui.admin.invitations",
|
||||||
"label": t("Benutzer-Einladungen"),
|
"label": t("Einladungen"),
|
||||||
"icon": "FaEnvelopeOpenText",
|
"icon": "FaEnvelopeOpenText",
|
||||||
"path": "/admin/invitations",
|
"path": "/admin/invitations",
|
||||||
"order": 20,
|
"order": 20,
|
||||||
|
|
@ -255,7 +224,7 @@ NAVIGATION_SECTIONS = [
|
||||||
{
|
{
|
||||||
"id": "admin-user-access-overview",
|
"id": "admin-user-access-overview",
|
||||||
"objectKey": "ui.admin.userAccessOverview",
|
"objectKey": "ui.admin.userAccessOverview",
|
||||||
"label": t("Benutzer-Zugriffsübersicht"),
|
"label": t("Zugriffe"),
|
||||||
"icon": "FaClipboardList",
|
"icon": "FaClipboardList",
|
||||||
"path": "/admin/user-access-overview",
|
"path": "/admin/user-access-overview",
|
||||||
"order": 30,
|
"order": 30,
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,23 @@ def resolveRoleLabels(db, ids: List[str]) -> Dict[str, Optional[str]]:
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def resolveFileLabels(db, ids: List[str]) -> Dict[str, Optional[str]]:
|
||||||
|
"""Resolve FileItem IDs to fileName. Returns None for unresolvable."""
|
||||||
|
if not ids:
|
||||||
|
return {}
|
||||||
|
from modules.datamodels.datamodelFiles import FileItem as _FileItem
|
||||||
|
recs = db.getRecordset(
|
||||||
|
_FileItem,
|
||||||
|
recordFilter={"id": list(set(ids))},
|
||||||
|
) or []
|
||||||
|
out: Dict[str, Optional[str]] = {i: None for i in ids}
|
||||||
|
for r in recs:
|
||||||
|
fid = r.get("id")
|
||||||
|
if fid:
|
||||||
|
out[fid] = r.get("fileName") or None
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Resolver registry
|
# Resolver registry
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -105,6 +122,7 @@ _BUILTIN_FK_RESOLVERS: Dict[str, Callable] = {
|
||||||
"FeatureInstance": resolveInstanceLabels,
|
"FeatureInstance": resolveInstanceLabels,
|
||||||
"UserInDB": resolveUserLabels,
|
"UserInDB": resolveUserLabels,
|
||||||
"Role": resolveRoleLabels,
|
"Role": resolveRoleLabels,
|
||||||
|
"FileItem": resolveFileLabels,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ def get_projects(
|
||||||
if mode == "filterValues":
|
if mode == "filterValues":
|
||||||
if not column:
|
if not column:
|
||||||
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
||||||
enrichRowsWithFkLabels(itemDicts, Projekt, db=interface.db)
|
enrichRowsWithFkLabels(itemDicts, Projekt, db=getRootInterface().db)
|
||||||
return handleFilterValuesInMemory(itemDicts, column, pagination)
|
return handleFilterValuesInMemory(itemDicts, column, pagination)
|
||||||
return handleIdsInMemory(itemDicts, pagination)
|
return handleIdsInMemory(itemDicts, pagination)
|
||||||
|
|
||||||
|
|
@ -271,7 +271,9 @@ def get_projects(
|
||||||
paginationParams = _parsePagination(pagination)
|
paginationParams = _parsePagination(pagination)
|
||||||
if paginationParams:
|
if paginationParams:
|
||||||
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
||||||
|
enrichRowsWithFkLabels(itemDicts, Projekt, db=getRootInterface().db)
|
||||||
filtered = applyFiltersAndSort(itemDicts, paginationParams)
|
filtered = applyFiltersAndSort(itemDicts, paginationParams)
|
||||||
total_items = len(filtered)
|
total_items = len(filtered)
|
||||||
total_pages = (total_items + paginationParams.pageSize - 1) // paginationParams.pageSize
|
total_pages = (total_items + paginationParams.pageSize - 1) // paginationParams.pageSize
|
||||||
|
|
@ -289,7 +291,10 @@ def get_projects(
|
||||||
filters=paginationParams.filters
|
filters=paginationParams.filters
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return PaginatedResponse(items=items, pagination=None)
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
||||||
|
enrichRowsWithFkLabels(itemDicts, Projekt, db=getRootInterface().db)
|
||||||
|
return PaginatedResponse(items=itemDicts, pagination=None)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{instanceId}/projects/{projectId}", response_model=Projekt)
|
@router.get("/{instanceId}/projects/{projectId}", response_model=Projekt)
|
||||||
|
|
@ -405,7 +410,7 @@ def get_parcels(
|
||||||
if mode == "filterValues":
|
if mode == "filterValues":
|
||||||
if not column:
|
if not column:
|
||||||
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
||||||
enrichRowsWithFkLabels(itemDicts, Parzelle, db=interface.db)
|
enrichRowsWithFkLabels(itemDicts, Parzelle, db=getRootInterface().db)
|
||||||
return handleFilterValuesInMemory(itemDicts, column, pagination)
|
return handleFilterValuesInMemory(itemDicts, column, pagination)
|
||||||
return handleIdsInMemory(itemDicts, pagination)
|
return handleIdsInMemory(itemDicts, pagination)
|
||||||
|
|
||||||
|
|
@ -413,7 +418,9 @@ def get_parcels(
|
||||||
paginationParams = _parsePagination(pagination)
|
paginationParams = _parsePagination(pagination)
|
||||||
if paginationParams:
|
if paginationParams:
|
||||||
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
||||||
|
enrichRowsWithFkLabels(itemDicts, Parzelle, db=getRootInterface().db)
|
||||||
filtered = applyFiltersAndSort(itemDicts, paginationParams)
|
filtered = applyFiltersAndSort(itemDicts, paginationParams)
|
||||||
total_items = len(filtered)
|
total_items = len(filtered)
|
||||||
total_pages = (total_items + paginationParams.pageSize - 1) // paginationParams.pageSize
|
total_pages = (total_items + paginationParams.pageSize - 1) // paginationParams.pageSize
|
||||||
|
|
@ -431,7 +438,10 @@ def get_parcels(
|
||||||
filters=paginationParams.filters
|
filters=paginationParams.filters
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return PaginatedResponse(items=items, pagination=None)
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
itemDicts = [i.model_dump() if hasattr(i, 'model_dump') else i for i in items]
|
||||||
|
enrichRowsWithFkLabels(itemDicts, Parzelle, db=getRootInterface().db)
|
||||||
|
return PaginatedResponse(items=itemDicts, pagination=None)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{instanceId}/parcels/{parcelId}", response_model=Parzelle)
|
@router.get("/{instanceId}/parcels/{parcelId}", response_model=Parzelle)
|
||||||
|
|
|
||||||
|
|
@ -437,7 +437,7 @@ def get_organisations(
|
||||||
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeOrganisation, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeOrganisation, db=getRootInterface().db)
|
||||||
return {
|
return {
|
||||||
"items": enriched,
|
"items": enriched,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
|
|
@ -450,7 +450,7 @@ def get_organisations(
|
||||||
).model_dump(),
|
).model_dump(),
|
||||||
}
|
}
|
||||||
items = result if isinstance(result, list) else result.items
|
items = result if isinstance(result, list) else result.items
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeOrganisation, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeOrganisation, db=getRootInterface().db)
|
||||||
return {"items": enriched, "pagination": None}
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -557,7 +557,7 @@ def get_roles(
|
||||||
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeRole, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeRole, db=getRootInterface().db)
|
||||||
return {
|
return {
|
||||||
"items": enriched,
|
"items": enriched,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
|
|
@ -570,7 +570,7 @@ def get_roles(
|
||||||
).model_dump(),
|
).model_dump(),
|
||||||
}
|
}
|
||||||
items = result if isinstance(result, list) else result.items
|
items = result if isinstance(result, list) else result.items
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeRole, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeRole, db=getRootInterface().db)
|
||||||
return {"items": enriched, "pagination": None}
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -677,7 +677,7 @@ def get_all_access(
|
||||||
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeAccess, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeAccess, db=getRootInterface().db)
|
||||||
return {
|
return {
|
||||||
"items": enriched,
|
"items": enriched,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
|
|
@ -690,7 +690,7 @@ def get_all_access(
|
||||||
).model_dump(),
|
).model_dump(),
|
||||||
}
|
}
|
||||||
items = result if isinstance(result, list) else result.items
|
items = result if isinstance(result, list) else result.items
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeAccess, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeAccess, db=getRootInterface().db)
|
||||||
return {"items": enriched, "pagination": None}
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -827,7 +827,7 @@ def get_contracts(
|
||||||
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
return [r.model_dump() if hasattr(r, "model_dump") else r for r in items]
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeContract, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(result.items), TrusteeContract, db=getRootInterface().db)
|
||||||
return {
|
return {
|
||||||
"items": enriched,
|
"items": enriched,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
|
|
@ -840,7 +840,7 @@ def get_contracts(
|
||||||
).model_dump(),
|
).model_dump(),
|
||||||
}
|
}
|
||||||
items = result if isinstance(result, list) else result.items
|
items = result if isinstance(result, list) else result.items
|
||||||
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeContract, db=interface.db)
|
enriched = enrichRowsWithFkLabels(_toDicts(items), TrusteeContract, db=getRootInterface().db)
|
||||||
return {"items": enriched, "pagination": None}
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -953,6 +953,7 @@ def get_documents(
|
||||||
context: RequestContext = Depends(getRequestContext)
|
context: RequestContext = Depends(getRequestContext)
|
||||||
):
|
):
|
||||||
"""Get all documents (metadata only) with optional pagination."""
|
"""Get all documents (metadata only) with optional pagination."""
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
mandateId = _validateInstanceAccess(instanceId, context)
|
mandateId = _validateInstanceAccess(instanceId, context)
|
||||||
|
|
||||||
if mode in ("filterValues", "ids"):
|
if mode in ("filterValues", "ids"):
|
||||||
|
|
@ -966,8 +967,9 @@ def get_documents(
|
||||||
return [r.model_dump() if hasattr(r, 'model_dump') else r for r in items]
|
return [r.model_dump() if hasattr(r, 'model_dump') else r for r in items]
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
|
enriched = enrichRowsWithFkLabels(_itemsToDicts(result.items), TrusteeDocument, db=getRootInterface().db)
|
||||||
return {
|
return {
|
||||||
"items": _itemsToDicts(result.items),
|
"items": enriched,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
currentPage=paginationParams.page or 1,
|
currentPage=paginationParams.page or 1,
|
||||||
pageSize=paginationParams.pageSize or 20,
|
pageSize=paginationParams.pageSize or 20,
|
||||||
|
|
@ -978,7 +980,8 @@ def get_documents(
|
||||||
).model_dump(),
|
).model_dump(),
|
||||||
}
|
}
|
||||||
items = result if isinstance(result, list) else result.items
|
items = result if isinstance(result, list) else result.items
|
||||||
return {"items": _itemsToDicts(items), "pagination": None}
|
enriched = enrichRowsWithFkLabels(_itemsToDicts(items), TrusteeDocument, db=getRootInterface().db)
|
||||||
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
def _handleDocumentMode(instanceId, mandateId, mode, column, pagination, context):
|
def _handleDocumentMode(instanceId, mandateId, mode, column, pagination, context):
|
||||||
|
|
@ -991,7 +994,7 @@ def _handleDocumentMode(instanceId, mandateId, mode, column, pagination, context
|
||||||
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
||||||
result = interface.getAllDocuments(None)
|
result = interface.getAllDocuments(None)
|
||||||
items = [r.model_dump() if hasattr(r, 'model_dump') else r for r in (result.items if hasattr(result, 'items') else result)]
|
items = [r.model_dump() if hasattr(r, 'model_dump') else r for r in (result.items if hasattr(result, 'items') else result)]
|
||||||
enrichRowsWithFkLabels(items, TrusteeDocument, db=interface.db)
|
enrichRowsWithFkLabels(items, TrusteeDocument, db=getRootInterface().db)
|
||||||
return handleFilterValuesInMemory(items, column, pagination)
|
return handleFilterValuesInMemory(items, column, pagination)
|
||||||
if mode == "ids":
|
if mode == "ids":
|
||||||
result = interface.getAllDocuments(None)
|
result = interface.getAllDocuments(None)
|
||||||
|
|
@ -1229,6 +1232,7 @@ def get_positions(
|
||||||
context: RequestContext = Depends(getRequestContext)
|
context: RequestContext = Depends(getRequestContext)
|
||||||
):
|
):
|
||||||
"""Get all positions with optional pagination."""
|
"""Get all positions with optional pagination."""
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
mandateId = _validateInstanceAccess(instanceId, context)
|
mandateId = _validateInstanceAccess(instanceId, context)
|
||||||
|
|
||||||
if mode in ("filterValues", "ids"):
|
if mode in ("filterValues", "ids"):
|
||||||
|
|
@ -1241,9 +1245,12 @@ def get_positions(
|
||||||
def _itemsToDicts(items):
|
def _itemsToDicts(items):
|
||||||
return [r.model_dump() if hasattr(r, 'model_dump') else r for r in items]
|
return [r.model_dump() if hasattr(r, 'model_dump') else r for r in items]
|
||||||
|
|
||||||
|
featureResolvers = _buildFeatureInternalResolvers(TrusteePosition, interface.db)
|
||||||
|
|
||||||
if paginationParams and hasattr(result, 'items'):
|
if paginationParams and hasattr(result, 'items'):
|
||||||
items = _itemsToDicts(result.items)
|
items = _itemsToDicts(result.items)
|
||||||
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
||||||
|
enrichRowsWithFkLabels(items, TrusteePosition, db=getRootInterface().db, extraResolvers=featureResolvers or None)
|
||||||
return {
|
return {
|
||||||
"items": items,
|
"items": items,
|
||||||
"pagination": PaginationMetadata(
|
"pagination": PaginationMetadata(
|
||||||
|
|
@ -1258,6 +1265,7 @@ def get_positions(
|
||||||
rawItems = result if isinstance(result, list) else result.items
|
rawItems = result if isinstance(result, list) else result.items
|
||||||
items = _itemsToDicts(rawItems)
|
items = _itemsToDicts(rawItems)
|
||||||
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
||||||
|
enrichRowsWithFkLabels(items, TrusteePosition, db=getRootInterface().db, extraResolvers=featureResolvers or None)
|
||||||
return {"items": items, "pagination": None}
|
return {"items": items, "pagination": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1273,7 +1281,7 @@ def _handlePositionMode(instanceId, mandateId, mode, column, pagination, context
|
||||||
result = interface.getAllPositions(None)
|
result = interface.getAllPositions(None)
|
||||||
items = [r.model_dump() if hasattr(r, 'model_dump') else r for r in (result.items if hasattr(result, 'items') else result)]
|
items = [r.model_dump() if hasattr(r, 'model_dump') else r for r in (result.items if hasattr(result, 'items') else result)]
|
||||||
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
_enrichPositionsWithSyncStatus(items, interface, instanceId)
|
||||||
enrichRowsWithFkLabels(items, TrusteePositionView, db=interface.db)
|
enrichRowsWithFkLabels(items, TrusteePositionView, db=getRootInterface().db)
|
||||||
return handleFilterValuesInMemory(items, column, pagination)
|
return handleFilterValuesInMemory(items, column, pagination)
|
||||||
if mode == "ids":
|
if mode == "ids":
|
||||||
result = interface.getAllPositions(None)
|
result = interface.getAllPositions(None)
|
||||||
|
|
@ -2075,7 +2083,7 @@ def _paginatedReadEndpoint(
|
||||||
rawItems = result.items if hasattr(result, "items") else result
|
rawItems = result.items if hasattr(result, "items") else result
|
||||||
items = [r.model_dump() if hasattr(r, "model_dump") else r for r in rawItems]
|
items = [r.model_dump() if hasattr(r, "model_dump") else r for r in rawItems]
|
||||||
featureResolvers = _buildFeatureInternalResolvers(modelClass, interface.db)
|
featureResolvers = _buildFeatureInternalResolvers(modelClass, interface.db)
|
||||||
enrichRowsWithFkLabels(items, modelClass, db=interface.db, extraResolvers=featureResolvers or None)
|
enrichRowsWithFkLabels(items, modelClass, db=getRootInterface().db, extraResolvers=featureResolvers or None)
|
||||||
return handleFilterValuesInMemory(items, column, pagination)
|
return handleFilterValuesInMemory(items, column, pagination)
|
||||||
|
|
||||||
if mode == "ids":
|
if mode == "ids":
|
||||||
|
|
@ -2113,7 +2121,7 @@ def _paginatedReadEndpoint(
|
||||||
if paginationParams and hasattr(result, "items"):
|
if paginationParams and hasattr(result, "items"):
|
||||||
enriched = enrichRowsWithFkLabels(
|
enriched = enrichRowsWithFkLabels(
|
||||||
_itemsToDicts(result.items), modelClass,
|
_itemsToDicts(result.items), modelClass,
|
||||||
db=interface.db, extraResolvers=featureResolvers or None,
|
db=getRootInterface().db, extraResolvers=featureResolvers or None,
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
"items": enriched,
|
"items": enriched,
|
||||||
|
|
@ -2129,7 +2137,7 @@ def _paginatedReadEndpoint(
|
||||||
items = result.items if hasattr(result, "items") else result
|
items = result.items if hasattr(result, "items") else result
|
||||||
enriched = enrichRowsWithFkLabels(
|
enriched = enrichRowsWithFkLabels(
|
||||||
_itemsToDicts(items), modelClass,
|
_itemsToDicts(items), modelClass,
|
||||||
db=interface.db, extraResolvers=featureResolvers or None,
|
db=getRootInterface().db, extraResolvers=featureResolvers or None,
|
||||||
)
|
)
|
||||||
return {"items": enriched, "pagination": None}
|
return {"items": enriched, "pagination": None}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -472,12 +472,13 @@ def list_feature_instances(
|
||||||
|
|
||||||
items = [inst.model_dump() for inst in instances]
|
items = [inst.model_dump() for inst in instances]
|
||||||
|
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
from modules.datamodels.datamodelFeatures import FeatureInstance
|
||||||
|
enrichRowsWithFkLabels(items, FeatureInstance, db=rootInterface.db)
|
||||||
|
|
||||||
if mode == "filterValues":
|
if mode == "filterValues":
|
||||||
if not column:
|
if not column:
|
||||||
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
raise HTTPException(status_code=400, detail="column parameter required for mode=filterValues")
|
||||||
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
|
||||||
from modules.datamodels.datamodelFeatures import FeatureInstance
|
|
||||||
enrichRowsWithFkLabels(items, FeatureInstance, db=rootInterface.db)
|
|
||||||
return handleFilterValuesInMemory(items, column, pagination)
|
return handleFilterValuesInMemory(items, column, pagination)
|
||||||
|
|
||||||
if mode == "ids":
|
if mode == "ids":
|
||||||
|
|
|
||||||
|
|
@ -940,6 +940,8 @@ def list_roles(
|
||||||
|
|
||||||
if paginationParams:
|
if paginationParams:
|
||||||
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
from modules.dbHelpers.paginationHelpers import applyFiltersAndSort
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
enrichRowsWithFkLabels(result, Role, db=interface.db)
|
||||||
sortedResult = applyFiltersAndSort(result, paginationParams)
|
sortedResult = applyFiltersAndSort(result, paginationParams)
|
||||||
totalItems = len(sortedResult)
|
totalItems = len(sortedResult)
|
||||||
totalPages = math.ceil(totalItems / paginationParams.pageSize) if totalItems > 0 else 0
|
totalPages = math.ceil(totalItems / paginationParams.pageSize) if totalItems > 0 else 0
|
||||||
|
|
@ -959,7 +961,8 @@ def list_roles(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# No pagination - return all roles
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
enrichRowsWithFkLabels(result, Role, db=interface.db)
|
||||||
return PaginatedResponse(
|
return PaginatedResponse(
|
||||||
items=result,
|
items=result,
|
||||||
pagination=None
|
pagination=None
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,16 @@ async def getNeutralizationMappings(
|
||||||
|
|
||||||
_enrichUserAndInstanceLabels(items, context)
|
_enrichUserAndInstanceLabels(items, context)
|
||||||
|
|
||||||
|
fileIds = list({r.get("fileId") for r in items if r.get("fileId")})
|
||||||
|
if fileIds:
|
||||||
|
from modules.dbHelpers.fkLabelResolver import resolveFileLabels
|
||||||
|
from modules.interfaces.interfaceDbApp import getRootInterface
|
||||||
|
fileMap = resolveFileLabels(getRootInterface().db, fileIds)
|
||||||
|
for r in items:
|
||||||
|
fid = r.get("fileId")
|
||||||
|
if fid and fid in fileMap:
|
||||||
|
r["fileIdLabel"] = fileMap[fid] or fid
|
||||||
|
|
||||||
if mode == "filterValues" and column:
|
if mode == "filterValues" and column:
|
||||||
items = _applySortFilterSearch(items, filtersJson=filters)
|
items = _applySortFilterSearch(items, filtersJson=filters)
|
||||||
return _distinctColumnValues(items, column)
|
return _distinctColumnValues(items, column)
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ def get_prompts(
|
||||||
|
|
||||||
def _promptsToEnrichedDicts(promptItems):
|
def _promptsToEnrichedDicts(promptItems):
|
||||||
dicts = [r.model_dump() if hasattr(r, 'model_dump') else (dict(r) if not isinstance(r, dict) else r) for r in promptItems]
|
dicts = [r.model_dump() if hasattr(r, 'model_dump') else (dict(r) if not isinstance(r, dict) else r) for r in promptItems]
|
||||||
enrichRowsWithFkLabels(dicts, Prompt, db=managementInterface.db)
|
enrichRowsWithFkLabels(dicts, Prompt, db=getAppInterface(currentUser).db)
|
||||||
return dicts
|
return dicts
|
||||||
|
|
||||||
managementInterface = interfaceDbManagement.getInterface(currentUser)
|
managementInterface = interfaceDbManagement.getInterface(currentUser)
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,10 @@ def getAllSubscriptions(
|
||||||
raise HTTPException(status_code=400, detail=f"Invalid pagination parameter: {str(e)}")
|
raise HTTPException(status_code=400, detail=f"Invalid pagination parameter: {str(e)}")
|
||||||
|
|
||||||
enriched = _buildEnrichedSubscriptions()
|
enriched = _buildEnrichedSubscriptions()
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
from modules.datamodels.datamodelSubscription import MandateSubscription
|
||||||
|
from modules.interfaces.interfaceDbApp import getRootInterface as _getRootIf
|
||||||
|
enrichRowsWithFkLabels(enriched, MandateSubscription, db=_getRootIf().db)
|
||||||
filtered = applyFiltersAndSort(enriched, paginationParams)
|
filtered = applyFiltersAndSort(enriched, paginationParams)
|
||||||
|
|
||||||
if paginationParams:
|
if paginationParams:
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ async def _listWorkflows(
|
||||||
pagination: Optional[str] = Query(default=None),
|
pagination: Optional[str] = Query(default=None),
|
||||||
mandateId: Optional[str] = Query(default=None),
|
mandateId: Optional[str] = Query(default=None),
|
||||||
):
|
):
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
from modules.interfaces.interfaceDbApp import getRootInterface as _getRootIface
|
||||||
db = _getWorkflowAutomationDb()
|
db = _getWorkflowAutomationDb()
|
||||||
try:
|
try:
|
||||||
db._ensureTableExists(AutoWorkflow)
|
db._ensureTableExists(AutoWorkflow)
|
||||||
|
|
@ -76,6 +78,7 @@ async def _listWorkflows(
|
||||||
|
|
||||||
params = _parsePaginationOr400(pagination)
|
params = _parsePaginationOr400(pagination)
|
||||||
records = db.getRecordset(AutoWorkflow, recordFilter=scopeFilter)
|
records = db.getRecordset(AutoWorkflow, recordFilter=scopeFilter)
|
||||||
|
enrichRowsWithFkLabels(records or [], AutoWorkflow, db=_getRootIface().db)
|
||||||
if params:
|
if params:
|
||||||
filtered = applyFiltersAndSort(records or [], params)
|
filtered = applyFiltersAndSort(records or [], params)
|
||||||
pageItems, totalItems = paginateInMemory(filtered, params)
|
pageItems, totalItems = paginateInMemory(filtered, params)
|
||||||
|
|
@ -169,6 +172,8 @@ async def _listRuns(
|
||||||
mandateId: Optional[str] = Query(default=None),
|
mandateId: Optional[str] = Query(default=None),
|
||||||
workflowId: Optional[str] = Query(default=None),
|
workflowId: Optional[str] = Query(default=None),
|
||||||
):
|
):
|
||||||
|
from modules.dbHelpers.fkLabelResolver import enrichRowsWithFkLabels
|
||||||
|
from modules.interfaces.interfaceDbApp import getRootInterface as _getRootIface
|
||||||
db = _getWorkflowAutomationDb()
|
db = _getWorkflowAutomationDb()
|
||||||
try:
|
try:
|
||||||
db._ensureTableExists(AutoRun)
|
db._ensureTableExists(AutoRun)
|
||||||
|
|
@ -185,6 +190,15 @@ async def _listRuns(
|
||||||
|
|
||||||
params = _parsePaginationOr400(pagination)
|
params = _parsePaginationOr400(pagination)
|
||||||
records = db.getRecordset(AutoRun, recordFilter=scopeFilter)
|
records = db.getRecordset(AutoRun, recordFilter=scopeFilter)
|
||||||
|
|
||||||
|
def _resolveWorkflowLabels(ids):
|
||||||
|
wfRecs = db.getRecordset(AutoWorkflow, recordFilter={"id": list(set(ids))}) or []
|
||||||
|
return {r.get("id"): r.get("label") or r.get("name") for r in wfRecs}
|
||||||
|
|
||||||
|
enrichRowsWithFkLabels(
|
||||||
|
records or [], AutoRun, db=_getRootIface().db,
|
||||||
|
extraResolvers={"workflowId": _resolveWorkflowLabels},
|
||||||
|
)
|
||||||
if params:
|
if params:
|
||||||
filtered = applyFiltersAndSort(records or [], params)
|
filtered = applyFiltersAndSort(records or [], params)
|
||||||
pageItems, totalItems = paginateInMemory(filtered, params)
|
pageItems, totalItems = paginateInMemory(filtered, params)
|
||||||
|
|
@ -991,7 +1005,7 @@ def _getMetrics(
|
||||||
try:
|
try:
|
||||||
workflows = db.getRecordset(AutoWorkflow, recordFilter=scopeFilter) or [] if db._ensureTableExists(AutoWorkflow) else []
|
workflows = db.getRecordset(AutoWorkflow, recordFilter=scopeFilter) or [] if db._ensureTableExists(AutoWorkflow) else []
|
||||||
wfIds = [w.get("id") for w in workflows]
|
wfIds = [w.get("id") for w in workflows]
|
||||||
runFilter = {"workflowId": {"$in": wfIds}} if wfIds else {"workflowId": "__none__"}
|
runFilter = {"workflowId": wfIds} if wfIds else {"workflowId": "__none__"}
|
||||||
runs = db.getRecordset(AutoRun, recordFilter=runFilter) or [] if db._ensureTableExists(AutoRun) else []
|
runs = db.getRecordset(AutoRun, recordFilter=runFilter) or [] if db._ensureTableExists(AutoRun) else []
|
||||||
tasks = db.getRecordset(AutoTask, recordFilter=runFilter) or [] if db._ensureTableExists(AutoTask) else []
|
tasks = db.getRecordset(AutoTask, recordFilter=runFilter) or [] if db._ensureTableExists(AutoTask) else []
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -1275,7 +1289,8 @@ def _getRunDetail(
|
||||||
if tid:
|
if tid:
|
||||||
try:
|
try:
|
||||||
from modules.dbHelpers.fkLabelResolver import resolveInstanceLabels
|
from modules.dbHelpers.fkLabelResolver import resolveInstanceLabels
|
||||||
labelMap = resolveInstanceLabels(db, [tid])
|
from modules.interfaces.interfaceDbApp import getRootInterface as _getRootIface
|
||||||
|
labelMap = resolveInstanceLabels(_getRootIface().db, [tid])
|
||||||
targetInstanceLabel = labelMap.get(tid)
|
targetInstanceLabel = labelMap.get(tid)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
@ -1465,6 +1480,85 @@ async def _executeWorkflow(
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/execute")
|
||||||
|
@limiter.limit("30/minute")
|
||||||
|
async def _executeWorkflowFromBody(
|
||||||
|
request: Request,
|
||||||
|
body: dict = Body(..., description="{ workflowId?, graph?, targetInstanceId?, payload?, runEnvelope? }"),
|
||||||
|
context: RequestContext = Depends(getRequestContext),
|
||||||
|
) -> dict:
|
||||||
|
"""Execute a workflow — workflowId from body or ad-hoc graph execution."""
|
||||||
|
from modules.workflowAutomation.mainWorkflowAutomation import _getWorkflowAutomationServices
|
||||||
|
from modules.workflowAutomation.engine.executionEngine import executeGraph
|
||||||
|
from modules.interfaces.interfaceWorkflowAutomation import _getWorkflowAutomationInterface
|
||||||
|
from modules.workflows.processing.shared.methodDiscovery import discoverMethods
|
||||||
|
|
||||||
|
userId = str(context.user.id) if context.user else None
|
||||||
|
workflowId = body.get("workflowId") or ""
|
||||||
|
targetInstanceId = body.get("targetInstanceId") or ""
|
||||||
|
|
||||||
|
wf = None
|
||||||
|
if workflowId:
|
||||||
|
db = _getWorkflowAutomationDb()
|
||||||
|
try:
|
||||||
|
db._ensureTableExists(AutoWorkflow)
|
||||||
|
wf = db.getRecord(AutoWorkflow, workflowId)
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
if not wf:
|
||||||
|
raise HTTPException(status_code=404, detail=routeApiMsg("Workflow not found"))
|
||||||
|
_validateWorkflowAccess(context, wf, "execute")
|
||||||
|
|
||||||
|
mandateId = (wf.get("mandateId") if wf else None) or str(context.mandateId or "")
|
||||||
|
instanceId = (wf.get("featureInstanceId") if wf else None) or targetInstanceId or str(context.featureInstanceId or "")
|
||||||
|
targetFeatureInstanceId = (wf.get("targetFeatureInstanceId") if wf else None) or targetInstanceId or ""
|
||||||
|
|
||||||
|
services = _getWorkflowAutomationServices(
|
||||||
|
context.user,
|
||||||
|
mandateId=mandateId,
|
||||||
|
featureInstanceId=instanceId,
|
||||||
|
)
|
||||||
|
discoverMethods(services)
|
||||||
|
|
||||||
|
graph = body.get("graph") or body.get("payload") or {}
|
||||||
|
if wf and not (graph.get("nodes") or []):
|
||||||
|
graph = wf.get("graph") or {}
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"workflowAutomation /execute: workflowId=%s nodes=%d userId=%s",
|
||||||
|
workflowId, len(graph.get("nodes") or []), userId,
|
||||||
|
)
|
||||||
|
|
||||||
|
workflowForEnvelope = wf
|
||||||
|
runEnv = _buildExecuteRunEnvelope(
|
||||||
|
body,
|
||||||
|
workflowForEnvelope,
|
||||||
|
userId,
|
||||||
|
getattr(context.user, "language", None) if context.user else None,
|
||||||
|
)
|
||||||
|
wfLabel = (wf.get("label") if wf else None) or ""
|
||||||
|
|
||||||
|
iface = _getWorkflowAutomationInterface(context.user, mandateId, instanceId)
|
||||||
|
result = await executeGraph(
|
||||||
|
graph=graph,
|
||||||
|
services=services,
|
||||||
|
workflowId=workflowId or None,
|
||||||
|
instanceId=instanceId,
|
||||||
|
userId=userId,
|
||||||
|
mandateId=mandateId,
|
||||||
|
automation2_interface=iface,
|
||||||
|
run_envelope=runEnv,
|
||||||
|
label=wfLabel,
|
||||||
|
targetFeatureInstanceId=targetFeatureInstanceId,
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
"workflowAutomation /execute result: success=%s error=%s paused=%s",
|
||||||
|
result.get("success"), result.get("error"), result.get("paused"),
|
||||||
|
)
|
||||||
|
_startEmailPollerIfNeeded(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Version management
|
# Version management
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1003,6 +1003,9 @@ class ChatService:
|
||||||
"""Get workflow by ID by delegating to the chat interface"""
|
"""Get workflow by ID by delegating to the chat interface"""
|
||||||
try:
|
try:
|
||||||
logger.debug(f"getWorkflow called with workflowId: {workflowId}")
|
logger.debug(f"getWorkflow called with workflowId: {workflowId}")
|
||||||
|
if workflowId.startswith("transient-"):
|
||||||
|
logger.debug(f"getWorkflow: skipping DB lookup for transient workflow {workflowId}")
|
||||||
|
return None
|
||||||
result = self.interfaceDbChat.getWorkflow(workflowId)
|
result = self.interfaceDbChat.getWorkflow(workflowId)
|
||||||
if result:
|
if result:
|
||||||
logger.debug(f"getWorkflow returned workflow with ID: {result.id}")
|
logger.debug(f"getWorkflow returned workflow with ID: {result.id}")
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ model (see wiki/b-reference/platform/unified-data-bar.md):
|
||||||
- FdsRecordNode (+children)-- feature-owned FeatureDataSource records
|
- FdsRecordNode (+children)-- feature-owned FeatureDataSource records
|
||||||
- FdsFieldNode -- virtual per-column nodes under fdsTable
|
- FdsFieldNode -- virtual per-column nodes under fdsTable
|
||||||
|
|
||||||
The classes use `_inheritFlags.py` as a helper module for the actual
|
The classes use `modules/serviceCenter/core/flagResolution.py` as a helper module for the actual
|
||||||
walk/aggregate/cascade arithmetic, so the inheritance semantics live in
|
walk/aggregate/cascade arithmetic, so the inheritance semantics live in
|
||||||
one place. The classes themselves only express "what does this node type
|
one place. The classes themselves only express "what does this node type
|
||||||
DO" -- ownership, RBAC, persistence routing, child enumeration.
|
DO" -- ownership, RBAC, persistence routing, child enumeration.
|
||||||
|
|
|
||||||
|
|
@ -770,7 +770,7 @@ async def executeGraph(
|
||||||
|
|
||||||
waFileLogger: Optional[RunFileLogger] = None
|
waFileLogger: Optional[RunFileLogger] = None
|
||||||
nodeOutputs: Dict[str, Any] = dict(initialNodeOutputs or {})
|
nodeOutputs: Dict[str, Any] = dict(initialNodeOutputs or {})
|
||||||
if not runId and automation2_interface and workflowId and not is_resume:
|
if not runId and automation2_interface and not is_resume:
|
||||||
run_context = {
|
run_context = {
|
||||||
"connectionMap": connectionMap,
|
"connectionMap": connectionMap,
|
||||||
"inputSources": inputSources,
|
"inputSources": inputSources,
|
||||||
|
|
|
||||||
|
|
@ -599,9 +599,9 @@ class ActionNodeExecutor:
|
||||||
logger.exception("ActionNodeExecutor node %s FAILED: %s", nodeId, e)
|
logger.exception("ActionNodeExecutor node %s FAILED: %s", nodeId, e)
|
||||||
return _normalizeError(e, outputSchema)
|
return _normalizeError(e, outputSchema)
|
||||||
finally:
|
finally:
|
||||||
if chatService:
|
if self.services.chat:
|
||||||
try:
|
try:
|
||||||
chatService.progressLogFinish(nodeOperationId, actionSuccess)
|
self.services.chat.progressLogFinish(nodeOperationId, actionSuccess)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -630,11 +630,11 @@ class ActionNodeExecutor:
|
||||||
rawBytes = coerceDocumentDataToBytes(rawData)
|
rawBytes = coerceDocumentDataToBytes(rawData)
|
||||||
if isinstance(dumped, dict) and rawBytes:
|
if isinstance(dumped, dict) and rawBytes:
|
||||||
try:
|
try:
|
||||||
_mgmt = self.services.interfaceDbComponent
|
_chatSvc = self.services.chat
|
||||||
_docName = dumped.get("documentName") or f"workflow-result-{nodeId}.bin"
|
_docName = dumped.get("documentName") or f"workflow-result-{nodeId}.bin"
|
||||||
_mimeType = dumped.get("mimeType") or "application/octet-stream"
|
_mimeType = dumped.get("mimeType") or "application/octet-stream"
|
||||||
_fileItem = _mgmt.createFile(_docName, _mimeType, rawBytes, folderId=persist_folder_id)
|
_fileItem = _chatSvc.createFile(_docName, _mimeType, rawBytes, folderId=persist_folder_id)
|
||||||
_mgmt.createFileData(_fileItem.id, rawBytes)
|
_chatSvc.createFileData(_fileItem.id, rawBytes)
|
||||||
dumped["fileId"] = _fileItem.id
|
dumped["fileId"] = _fileItem.id
|
||||||
dumped["id"] = _fileItem.id
|
dumped["id"] = _fileItem.id
|
||||||
dumped["fileName"] = _fileItem.fileName
|
dumped["fileName"] = _fileItem.fileName
|
||||||
|
|
@ -656,7 +656,7 @@ class ActionNodeExecutor:
|
||||||
"documents": docsList,
|
"documents": docsList,
|
||||||
"count": len(docsList),
|
"count": len(docsList),
|
||||||
}
|
}
|
||||||
_attachConnectionProvenance(list_out, resolvedParams, outputSchema, chatService, self.services)
|
_attachConnectionProvenance(list_out, resolvedParams, outputSchema, self.services.chat, self.services)
|
||||||
return normalizeToSchema(list_out, outputSchema)
|
return normalizeToSchema(list_out, outputSchema)
|
||||||
|
|
||||||
extractedContext = ""
|
extractedContext = ""
|
||||||
|
|
@ -751,7 +751,7 @@ class ActionNodeExecutor:
|
||||||
"mode": data_dict.get("mode", resolvedParams.get("mode", "summarize")),
|
"mode": data_dict.get("mode", resolvedParams.get("mode", "summarize")),
|
||||||
"count": int(data_dict.get("count", 0)),
|
"count": int(data_dict.get("count", 0)),
|
||||||
}
|
}
|
||||||
_attachConnectionProvenance(cr_out, resolvedParams, outputSchema, chatService, self.services)
|
_attachConnectionProvenance(cr_out, resolvedParams, outputSchema, self.services.chat, self.services)
|
||||||
return normalizeToSchema(cr_out, outputSchema)
|
return normalizeToSchema(cr_out, outputSchema)
|
||||||
|
|
||||||
if nodeDef.get("popDocumentsFromOutput"):
|
if nodeDef.get("popDocumentsFromOutput"):
|
||||||
|
|
@ -760,7 +760,7 @@ class ActionNodeExecutor:
|
||||||
if outputSchema in ("AiResult", "ActionResult") and result.success:
|
if outputSchema in ("AiResult", "ActionResult") and result.success:
|
||||||
_attach_unified_presentation_data(out, node_def=nodeDef)
|
_attach_unified_presentation_data(out, node_def=nodeDef)
|
||||||
|
|
||||||
_attachConnectionProvenance(out, resolvedParams, outputSchema, chatService, self.services)
|
_attachConnectionProvenance(out, resolvedParams, outputSchema, self.services.chat, self.services)
|
||||||
|
|
||||||
# When the node declares ``surfaceDataAsTopLevel`` (typical for
|
# When the node declares ``surfaceDataAsTopLevel`` (typical for
|
||||||
# dynamic-schema context nodes whose output keys are graph-defined),
|
# dynamic-schema context nodes whose output keys are graph-defined),
|
||||||
|
|
|
||||||
|
|
@ -1194,8 +1194,8 @@ def _persist_extracted_image_parts(
|
||||||
)
|
)
|
||||||
return content_extracted_serial, artifacts
|
return content_extracted_serial, artifacts
|
||||||
|
|
||||||
if services and hasattr(services, "interfaceDbComponent"):
|
if services and hasattr(services, "chat"):
|
||||||
mgmt = services.interfaceDbComponent
|
mgmt = services.chat
|
||||||
else:
|
else:
|
||||||
from modules.interfaces.interfaceDbManagement import getInterface as _get_mgmt
|
from modules.interfaces.interfaceDbManagement import getInterface as _get_mgmt
|
||||||
from modules.security.rootAccess import getRootUser
|
from modules.security.rootAccess import getRootUser
|
||||||
|
|
@ -1206,7 +1206,7 @@ def _persist_extracted_image_parts(
|
||||||
return content_extracted_serial, artifacts
|
return content_extracted_serial, artifacts
|
||||||
|
|
||||||
if not mgmt:
|
if not mgmt:
|
||||||
logger.warning("extractContent image persist: no interfaceDbComponent available")
|
logger.warning("extractContent image persist: no chat service available")
|
||||||
return content_extracted_serial, artifacts
|
return content_extracted_serial, artifacts
|
||||||
|
|
||||||
stem = re.sub(r"[^\w\-]+", "_", name_stem).strip("_") or "extract"
|
stem = re.sub(r"[^\w\-]+", "_", name_stem).strip("_") or "extract"
|
||||||
|
|
@ -1310,11 +1310,11 @@ _IMAGE_MAX_DIMENSION = 1200
|
||||||
|
|
||||||
|
|
||||||
def _get_mgmt_for_presentation_render(services: Any) -> Optional[Any]:
|
def _get_mgmt_for_presentation_render(services: Any) -> Optional[Any]:
|
||||||
mgmt = getattr(services, "interfaceDbComponent", None) if services else None
|
|
||||||
if mgmt:
|
|
||||||
return mgmt
|
|
||||||
if not services:
|
if not services:
|
||||||
return None
|
return None
|
||||||
|
chat = getattr(services, "chat", None)
|
||||||
|
if chat:
|
||||||
|
return chat
|
||||||
try:
|
try:
|
||||||
import modules.interfaces.interfaceDbManagement as iface
|
import modules.interfaces.interfaceDbManagement as iface
|
||||||
|
|
||||||
|
|
@ -1385,7 +1385,7 @@ def _load_image_bytes_by_file_id(services: Any, file_id: str) -> Optional[bytes]
|
||||||
if not mgmt or not hasattr(mgmt, "getFileData"):
|
if not mgmt or not hasattr(mgmt, "getFileData"):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"no management interface available to load persisted image bytes — "
|
"no management interface available to load persisted image bytes — "
|
||||||
"services.interfaceDbComponent / mandate / instance must be set"
|
"services.chat / mandate / instance must be set"
|
||||||
)
|
)
|
||||||
return mgmt.getFileData(str(file_id))
|
return mgmt.getFileData(str(file_id))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import unittest
|
||||||
from typing import List
|
from typing import List
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from modules.serviceCenter.services.serviceKnowledge import _inheritFlags
|
from modules.serviceCenter.core import flagResolution as _inheritFlags
|
||||||
|
|
||||||
|
|
||||||
def _ds(idVal: str, path: str, **flags) -> dict:
|
def _ds(idVal: str, path: str, **flags) -> dict:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue