fix: Refactor Akte sync logic to handle multiple Redis queues and improve logging refactor: Enhance parameter flattening for EspoCRM API calls
166 lines
5.4 KiB
Python
166 lines
5.4 KiB
Python
"""
|
|
Advoware Service Wrapper
|
|
|
|
Extends AdvowareAPI with higher-level operations for business logic.
|
|
"""
|
|
|
|
from typing import Dict, Any, Optional
|
|
from services.advoware import AdvowareAPI
|
|
from services.logging_utils import get_service_logger
|
|
|
|
|
|
class AdvowareService:
|
|
"""
|
|
Service layer for Advoware operations.
|
|
Uses AdvowareAPI for API calls.
|
|
"""
|
|
|
|
def __init__(self, context=None):
|
|
self.api = AdvowareAPI(context)
|
|
self.context = context
|
|
self.logger = get_service_logger('advoware_service', context)
|
|
|
|
def _log(self, message: str, level: str = 'info') -> None:
|
|
"""Internal logging helper"""
|
|
log_func = getattr(self.logger, level, self.logger.info)
|
|
log_func(message)
|
|
|
|
async def api_call(self, *args, **kwargs):
|
|
"""Delegate api_call to underlying AdvowareAPI"""
|
|
return await self.api.api_call(*args, **kwargs)
|
|
|
|
# ========== BETEILIGTE ==========
|
|
|
|
async def get_beteiligter(self, betnr: int) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Load Beteiligte with all data.
|
|
|
|
Returns:
|
|
Beteiligte object or None
|
|
"""
|
|
try:
|
|
endpoint = f"api/v1/advonet/Beteiligte/{betnr}"
|
|
result = await self.api.api_call(endpoint, method='GET')
|
|
return result
|
|
except Exception as e:
|
|
self._log(f"[ADVO] Error loading Beteiligte {betnr}: {e}", level='error')
|
|
return None
|
|
|
|
# ========== KOMMUNIKATION ==========
|
|
|
|
async def create_kommunikation(self, betnr: int, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Create new Kommunikation.
|
|
|
|
Args:
|
|
betnr: Beteiligte number
|
|
data: {
|
|
'tlf': str, # Required
|
|
'bemerkung': str, # Optional
|
|
'kommKz': int, # Required (1-12)
|
|
'online': bool # Optional
|
|
}
|
|
|
|
Returns:
|
|
New Kommunikation with 'id' or None
|
|
"""
|
|
try:
|
|
endpoint = f"api/v1/advonet/Beteiligte/{betnr}/Kommunikationen"
|
|
result = await self.api.api_call(endpoint, method='POST', json_data=data)
|
|
|
|
if result:
|
|
self._log(f"[ADVO] ✅ Created Kommunikation: betnr={betnr}, kommKz={data.get('kommKz')}")
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
self._log(f"[ADVO] Error creating Kommunikation: {e}", level='error')
|
|
return None
|
|
|
|
async def update_kommunikation(self, betnr: int, komm_id: int, data: Dict[str, Any]) -> bool:
|
|
"""
|
|
Update existing Kommunikation.
|
|
|
|
Args:
|
|
betnr: Beteiligte number
|
|
komm_id: Kommunikation ID
|
|
data: {
|
|
'tlf': str, # Optional
|
|
'bemerkung': str, # Optional
|
|
'online': bool # Optional
|
|
}
|
|
|
|
NOTE: kommKz is READ-ONLY and cannot be changed
|
|
|
|
Returns:
|
|
True if successful
|
|
"""
|
|
try:
|
|
endpoint = f"api/v1/advonet/Beteiligte/{betnr}/Kommunikationen/{komm_id}"
|
|
await self.api.api_call(endpoint, method='PUT', json_data=data)
|
|
|
|
self._log(f"[ADVO] ✅ Updated Kommunikation: betnr={betnr}, komm_id={komm_id}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
self._log(f"[ADVO] Error updating Kommunikation: {e}", level='error')
|
|
return False
|
|
|
|
async def delete_kommunikation(self, betnr: int, komm_id: int) -> bool:
|
|
"""
|
|
Delete Kommunikation (currently returns 403 Forbidden).
|
|
|
|
NOTE: DELETE is disabled in Advoware API.
|
|
Use empty slots with empty_slot_marker instead.
|
|
|
|
Returns:
|
|
True if successful
|
|
"""
|
|
try:
|
|
endpoint = f"api/v1/advonet/Beteiligte/{betnr}/Kommunikationen/{komm_id}"
|
|
await self.api.api_call(endpoint, method='DELETE')
|
|
|
|
self._log(f"[ADVO] ✅ Deleted Kommunikation: betnr={betnr}, komm_id={komm_id}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
# Expected: 403 Forbidden
|
|
self._log(f"[ADVO] DELETE not allowed (expected): {e}", level='warning')
|
|
return False
|
|
|
|
# ========== AKTEN ==========
|
|
|
|
async def get_akte(self, akte_id: int) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Get Akte details including ablage status.
|
|
|
|
Args:
|
|
akte_id: Advoware Akte ID
|
|
|
|
Returns:
|
|
Akte details with fields:
|
|
- ablage: int (0 or 1, archive status)
|
|
- az: str (Aktenzeichen)
|
|
- rubrum: str
|
|
- referat: str
|
|
- wegen: str
|
|
|
|
Returns None if Akte not found
|
|
"""
|
|
try:
|
|
endpoint = f"api/v1/advonet/Akten/{akte_id}"
|
|
result = await self.api.api_call(endpoint, method='GET')
|
|
|
|
# API may return a list (batch response) or a single dict
|
|
if isinstance(result, list):
|
|
result = result[0] if result else None
|
|
|
|
if result:
|
|
self._log(f"[ADVO] ✅ Fetched Akte {akte_id}: {result.get('az', 'N/A')}")
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
self._log(f"[ADVO] Error loading Akte {akte_id}: {e}", level='error')
|
|
return None
|