Compare commits

...

3 Commits

20 changed files with 58 additions and 30 deletions

13
service-account.json Normal file
View File

@@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "bitbylaw-475919",
"private_key_id": "1b83e57147852a870e34df41fbcfec281dccaf33",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDCYbRo/sgisHAp\noMCZ4c1ijpJ6igaKv6b9DmB8nH+DZeiJiGIYpOSVvpbTGLX4C4bg8lzrP/cYMhwm\ni2LATOEi8fMQX4/9v4yxr6lc+341/6bZ5Zp0qepqhJazFjJOhty2KovqJebiAJXE\n4AtDV4kgNJHZKAi9bSx3N6ltTP/qUS5BRuws2nrC3iaI+pHWIjG4vhH7Sjp/Ga86\nI05IcLGDG/SUX3oqqwpjACNGI+9/8hCfeqyMUjPhn82xivGzw+z4nC2iwcnRgsHB\nFxr5kpamJMmNOiWtZaYOBJzIa5EL4cu7VCMVt80VbA/Ezci+WvpJJ7nn2gS0KJGP\nXcdXGsrNAgMBAAECggEAByQfGaBf6o5VgIysUWWZ7bNT2aFKfjxuPmu8dbeAzmtR\nsK52/srIBGGnxCzrOn1J65Jb1t9XDOeCYJQhq548wyjlB3FLUUTWlAyNCffJ+jfg\nga7NZC3TM9iXz2UoXKQtuu+Ii7CaxoDDqnjvUP5dRkvyyRSPGvkbd2xvEq86fk7Z\nbeqZoW3pmIqr4IMNRRRnXCq6bwCYg4paQZiyTnrX8JnnIq03hsSxcFEQsk78bsaF\nVBF76wtsjTFlcLTqzVzJDep15BXN/KP12bSgzlTC2P1lB97+XmrI+6/Cj6cv3Vda\nISgmEBZbeph+rBzJ4M+5R4wM9ygP2aGhsORTmzFMrQKBgQDu91WL8IXS9ZPUO26e\nutorkTlIAb1Jih8N5s4q07XF8SzScDw/E7ZdXAvylfHpnxLv1B6zi8r/MGAamHS9\n0iFzvrxE81s2h8U2bIhyADhkjGLQFXPK+cW62ym3ZATGExxWoQL9jpczsgNOv78d\n384w1bf4MBudlHhXj7Wt+dpK0wKBgQDQPMpm7l7lSBHRPOV2+Th0G1ExJAHhqrTC\nbx/X8e6WABsJ+o/N9ttrPsHlZ4lzhuNw5v0hYrPV0YrXRg98QqYUbKTrAHRIq4gL\nhnrmVDywTUPeU4PEoW0of8rQeQUzVCdw3dKhKTs6H9LN7VUy3mEu5L78mdPYQL2E\nwwNPZOHP3wKBgGg8dRFcslMqEfiyj/cnFEGK0EyrjZDFcfRTaDzgKlsUb3O/x1fQ\nVmz02LVRWLuKSu1YPqgc40hbJqCTPeELBtKBMYh2CqSHpqutvfrUQ8UAQ532rZKt\nTuXJ8bFwLHDmJydWhoJpr2S6Up0IIOp8FGnS37Of8HvVJoUzR5GC+ghHAoGAZLrj\nVcM9GEAyjjqc7V5FFrUYI2M9ncILynoitz0KonjOm5ce9QzSuyASfzwEW2QGpVi3\nXez2/RltxhDX8M30tLCRXjRMC9Md7iVRUhWxfb8Cc4uGlBlaSlr26r1/7IJqycgj\n2V2ujsFSIdcKfZ7g9+QjFuH6fgNjKdODyGYObZUCgYBTePTscIghcfq5aJiEcNR0\nGaCaVnXLMbWIXMNYBrDotD30j4J7TyPny2b3xv5tfSud/c+gWzzJy3QLQY56ab1s\n89gG0KHSNvsMK+pJsB+3b9C+pFMRIlzJPXS++tIyBSf3gwV5PInytkE1ZgB+EpEQ\nAmAF5lUQ4XydjX3MTT1S4A==\n-----END PRIVATE KEY-----\n",
"client_email": "bitbylaw-advoware-snyc@bitbylaw-475919.iam.gserviceaccount.com",
"client_id": "104069107394434106127",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/bitbylaw-advoware-snyc%40bitbylaw-475919.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View File

@@ -20,6 +20,10 @@ class AdvowareService:
self.api = AdvowareAPI(context)
self.context = context
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]:

View File

@@ -25,7 +25,7 @@ from services.advoware_service import AdvowareService
config = {
'name': 'Calendar Sync All Step',
'description': 'Receives sync-all event and emits individual events for oldest employees',
'flows': ['advoware'],
'flows': ['advoware-calendar-sync'],
'triggers': [
queue('calendar_sync_all')
],

View File

@@ -15,7 +15,7 @@ from motia import http, ApiRequest, ApiResponse, FlowContext
config = {
'name': 'Calendar Sync API Trigger',
'description': 'API endpoint for manual calendar sync triggering',
'flows': ['advoware'],
'flows': ['advoware-calendar-sync'],
'triggers': [
http('POST', '/advoware/calendar/sync')
],

View File

@@ -15,7 +15,7 @@ from motia import cron, FlowContext
config = {
'name': 'Calendar Sync Cron Job',
'description': 'Runs calendar sync automatically every 15 minutes',
'flows': ['advoware'],
'flows': ['advoware-calendar-sync'],
'triggers': [
cron("0 */15 * * * *") # Every 15 minutes (6-field: sec min hour day month weekday)
],

View File

@@ -937,7 +937,7 @@ async def process_updates(state, conn, service, calendar_id: str, kuerzel: str,
config = {
"name": "Calendar Sync Event Step",
"description": "Handles bidirectional calendar sync between Advoware and Google Calendar using Postgres as hub",
"flows": ["advoware"],
"flows": ["advoware-calendar-sync"],
"triggers": [
queue("calendar_sync_employee")
],

View File

@@ -18,20 +18,31 @@ logger = logging.getLogger(__name__)
def log_operation(level: str, message: str, context=None, **context_vars):
"""Centralized logging with context, supporting file and console logging."""
context_str = ' '.join(f"{k}={v}" for k, v in context_vars.items() if v is not None)
full_message = f"[{time.time()}] {message} {context_str}".strip()
full_message = f"{message} {context_str}".strip()
# Log via logger
if level == 'info':
logger.info(full_message)
elif level == 'warning':
logger.warning(full_message)
elif level == 'error':
logger.error(full_message)
elif level == 'debug':
logger.debug(full_message)
# Use ctx.logger if context is available (Motia III FlowContext)
if context and hasattr(context, 'logger'):
if level == 'info':
context.logger.info(full_message)
elif level == 'warning':
context.logger.warning(full_message)
elif level == 'error':
context.logger.error(full_message)
elif level == 'debug':
context.logger.debug(full_message)
else:
# Fallback to standard logger
if level == 'info':
logger.info(full_message)
elif level == 'warning':
logger.warning(full_message)
elif level == 'error':
logger.error(full_message)
elif level == 'debug':
logger.debug(full_message)
# Also log to console for journalctl visibility
print(f"[{level.upper()}] {full_message}")
# Also log to console for journalctl visibility
print(f"[{level.upper()}] {full_message}")
async def connect_db(context=None):

View File

@@ -7,7 +7,7 @@ from services.advoware import AdvowareAPI
config = {
"name": "Advoware Proxy DELETE",
"description": "Universal proxy for Advoware API (DELETE requests)",
"flows": ["advoware"],
"flows": ["advoware-proxy"],
"triggers": [
http("DELETE", "/advoware/proxy")
],

View File

@@ -7,7 +7,7 @@ from services.advoware import AdvowareAPI
config = {
"name": "Advoware Proxy GET",
"description": "Universal proxy for Advoware API (GET requests)",
"flows": ["advoware"],
"flows": ["advoware-proxy"],
"triggers": [
http("GET", "/advoware/proxy")
],

View File

@@ -7,7 +7,7 @@ from services.advoware import AdvowareAPI
config = {
"name": "Advoware Proxy POST",
"description": "Universal proxy for Advoware API (POST requests)",
"flows": ["advoware"],
"flows": ["advoware-proxy"],
"triggers": [
http("POST", "/advoware/proxy")
],

View File

@@ -7,7 +7,7 @@ from services.advoware import AdvowareAPI
config = {
"name": "Advoware Proxy PUT",
"description": "Universal proxy for Advoware API (PUT requests)",
"flows": ["advoware"],
"flows": ["advoware-proxy"],
"triggers": [
http("PUT", "/advoware/proxy")
],

View File

@@ -23,7 +23,7 @@ import os
config = {
"name": "VMH Bankverbindungen Sync Handler",
"description": "Zentraler Sync-Handler für Bankverbindungen (Webhooks + Cron Events)",
"flows": ["vmh"],
"flows": ["vmh-bankverbindungen"],
"triggers": [
{"type": "queue", "topic": "vmh.bankverbindungen.create"},
{"type": "queue", "topic": "vmh.bankverbindungen.update"},

View File

@@ -17,7 +17,7 @@ import datetime
config = {
"name": "VMH Beteiligte Sync Cron",
"description": "Prüft alle 15 Minuten welche Beteiligte synchronisiert werden müssen",
"flows": ["vmh"],
"flows": ["vmh-beteiligte"],
"triggers": [
cron("0 */15 * * * *") # Alle 15 Minuten (6-field format!)
],

View File

@@ -24,7 +24,7 @@ import os
config = {
"name": "VMH Beteiligte Sync Handler",
"description": "Zentraler Sync-Handler für Beteiligte (Webhooks + Cron Events)",
"flows": ["vmh"],
"flows": ["vmh-beteiligte"],
"triggers": [
{"type": "queue", "topic": "vmh.beteiligte.create"},
{"type": "queue", "topic": "vmh.beteiligte.update"},

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Bankverbindungen Create",
"description": "Empfängt Create-Webhooks von EspoCRM für Bankverbindungen",
"flows": ["vmh"],
"flows": ["vmh-bankverbindungen"],
"triggers": [
http("POST", "/vmh/webhook/bankverbindungen/create")
],

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Bankverbindungen Delete",
"description": "Empfängt Delete-Webhooks von EspoCRM für Bankverbindungen",
"flows": ["vmh"],
"flows": ["vmh-bankverbindungen"],
"triggers": [
http("POST", "/vmh/webhook/bankverbindungen/delete")
],

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Bankverbindungen Update",
"description": "Empfängt Update-Webhooks von EspoCRM für Bankverbindungen",
"flows": ["vmh"],
"flows": ["vmh-bankverbindungen"],
"triggers": [
http("POST", "/vmh/webhook/bankverbindungen/update")
],

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Beteiligte Create",
"description": "Empfängt Create-Webhooks von EspoCRM für Beteiligte",
"flows": ["vmh"],
"flows": ["vmh-beteiligte"],
"triggers": [
http("POST", "/vmh/webhook/beteiligte/create")
],

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Beteiligte Delete",
"description": "Empfängt Delete-Webhooks von EspoCRM für Beteiligte",
"flows": ["vmh"],
"flows": ["vmh-beteiligte"],
"triggers": [
http("POST", "/vmh/webhook/beteiligte/delete")
],

View File

@@ -8,7 +8,7 @@ from motia import FlowContext, http, ApiRequest, ApiResponse
config = {
"name": "VMH Webhook Beteiligte Update",
"description": "Empfängt Update-Webhooks von EspoCRM für Beteiligte",
"flows": ["vmh"],
"flows": ["vmh-beteiligte"],
"triggers": [
http("POST", "/vmh/webhook/beteiligte/update")
],