72 lines
3.5 KiB
Python
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))
|