gateway/modules/workflows/methods/methodTrustee/actions/syncToAccounting.py
2026-02-22 00:07:33 +01:00

72 lines
3.5 KiB
Python

# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
Sync trustee positions to accounting (Buha).
Input: featureInstanceId, documentList (reference to processDocuments result message).
Reads positionIds from the document and calls AccountingBridge.pushBatchToAccounting.
"""
import json
import logging
from typing import Dict, Any, List
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
from modules.datamodels.datamodelDocref import DocumentReferenceList
logger = logging.getLogger(__name__)
async def syncToAccounting(self, parameters: Dict[str, Any]) -> ActionResult:
"""
Push trustee positions to the configured accounting system.
documentList must reference the message from processDocuments (one document with JSON { positionIds, documentIds }).
"""
featureInstanceId = parameters.get("featureInstanceId") or (self.services.featureInstanceId if hasattr(self.services, "featureInstanceId") else None)
documentListParam = parameters.get("documentList")
if not featureInstanceId:
return ActionResult.isFailure(error="featureInstanceId is required")
if not documentListParam:
return ActionResult.isFailure(error="documentList is required (reference to processDocuments result)")
try:
docList = DocumentReferenceList.from_string_list(
documentListParam if isinstance(documentListParam, list) else [documentListParam]
)
chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
if not chatDocuments:
return ActionResult.isFailure(error="No document found for documentList; ensure processDocuments ran before this action")
# Expect one document (JSON with positionIds, documentIds)
doc = chatDocuments[0]
rawBytes = self.services.chat.getFileData(doc.fileId)
if not rawBytes:
return ActionResult.isFailure(error=f"Could not load document content for fileId={doc.fileId}")
content = rawBytes.decode("utf-8") if isinstance(rawBytes, bytes) else rawBytes
data = json.loads(content) if isinstance(content, str) else content
positionIds = data.get("positionIds") or []
if not positionIds:
return ActionResult.isSuccess(documents=[
ActionDocument(documentName="sync_result", documentData=json.dumps({"pushed": 0, "message": "No positionIds in document"}), mimeType="application/json")
])
from modules.features.trustee.interfaceFeatureTrustee import getInterface as getTrusteeInterface
from modules.features.trustee.accounting.accountingBridge import AccountingBridge
trusteeInterface = getTrusteeInterface(
self.services.user,
mandateId=self.services.mandateId,
featureInstanceId=featureInstanceId
)
bridge = AccountingBridge(trusteeInterface)
results = await bridge.pushBatchToAccounting(featureInstanceId, positionIds)
successCount = sum(1 for r in results if r.success)
summary = {"pushed": successCount, "total": len(positionIds), "results": [{"positionId": pid, "success": r.success, "error": getattr(r, "errorMessage", None)} for pid, r in zip(positionIds, results)]}
return ActionResult.isSuccess(documents=[
ActionDocument(documentName="sync_result", documentData=json.dumps(summary), mimeType="application/json")
])
except Exception as e:
logger.exception("syncToAccounting failed")
return ActionResult.isFailure(error=str(e))