116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
|
|
"""
|
||
|
|
Daily sync job for e-conomic chart of accounts (kontoplan)
|
||
|
|
|
||
|
|
Scheduled to run every day at 06:00
|
||
|
|
Updates the economic_accounts cache table with latest data from e-conomic API
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
from datetime import datetime
|
||
|
|
from app.core.database import execute_query, execute_update, execute_insert
|
||
|
|
from app.services.economic_service import get_economic_service
|
||
|
|
from app.core.config import settings
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
async def sync_economic_accounts():
|
||
|
|
"""
|
||
|
|
Sync e-conomic chart of accounts to local cache
|
||
|
|
|
||
|
|
This job:
|
||
|
|
1. Fetches all accounts from e-conomic API
|
||
|
|
2. Updates economic_accounts table
|
||
|
|
3. Logs sync statistics
|
||
|
|
"""
|
||
|
|
try:
|
||
|
|
logger.info("🔄 Starting daily e-conomic accounts sync...")
|
||
|
|
|
||
|
|
# Check if e-conomic is configured
|
||
|
|
if not settings.ECONOMIC_APP_SECRET_TOKEN or not settings.ECONOMIC_AGREEMENT_GRANT_TOKEN:
|
||
|
|
logger.warning("⚠️ e-conomic credentials not configured - skipping sync")
|
||
|
|
return {
|
||
|
|
"success": False,
|
||
|
|
"reason": "e-conomic credentials not configured"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get economic service
|
||
|
|
economic_service = get_economic_service()
|
||
|
|
|
||
|
|
# Fetch accounts from e-conomic
|
||
|
|
logger.info("📥 Fetching accounts from e-conomic API...")
|
||
|
|
accounts = economic_service.get_accounts()
|
||
|
|
|
||
|
|
if not accounts:
|
||
|
|
logger.warning("⚠️ No accounts returned from e-conomic API")
|
||
|
|
return {
|
||
|
|
"success": False,
|
||
|
|
"reason": "No accounts returned from API"
|
||
|
|
}
|
||
|
|
|
||
|
|
logger.info(f"📦 Fetched {len(accounts)} accounts from e-conomic")
|
||
|
|
|
||
|
|
# Update database - upsert each account
|
||
|
|
updated_count = 0
|
||
|
|
inserted_count = 0
|
||
|
|
|
||
|
|
for account in accounts:
|
||
|
|
account_number = account.get('accountNumber')
|
||
|
|
name = account.get('name')
|
||
|
|
account_type = account.get('accountType')
|
||
|
|
vat_code = account.get('vatCode', {}).get('vatCode') if account.get('vatCode') else None
|
||
|
|
|
||
|
|
if not account_number:
|
||
|
|
continue
|
||
|
|
|
||
|
|
# Check if account exists
|
||
|
|
existing = execute_query(
|
||
|
|
"SELECT account_number FROM economic_accounts WHERE account_number = %s",
|
||
|
|
(account_number,)
|
||
|
|
)
|
||
|
|
|
||
|
|
if existing:
|
||
|
|
# Update existing
|
||
|
|
execute_update(
|
||
|
|
"""UPDATE economic_accounts
|
||
|
|
SET name = %s, account_type = %s, vat_code = %s,
|
||
|
|
updated_at = CURRENT_TIMESTAMP
|
||
|
|
WHERE account_number = %s""",
|
||
|
|
(name, account_type, vat_code, account_number)
|
||
|
|
)
|
||
|
|
updated_count += 1
|
||
|
|
else:
|
||
|
|
# Insert new
|
||
|
|
execute_insert(
|
||
|
|
"""INSERT INTO economic_accounts
|
||
|
|
(account_number, name, account_type, vat_code, updated_at)
|
||
|
|
VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)""",
|
||
|
|
(account_number, name, account_type, vat_code)
|
||
|
|
)
|
||
|
|
inserted_count += 1
|
||
|
|
|
||
|
|
logger.info(f"✅ e-conomic accounts sync complete: {inserted_count} inserted, {updated_count} updated")
|
||
|
|
|
||
|
|
return {
|
||
|
|
"success": True,
|
||
|
|
"fetched": len(accounts),
|
||
|
|
"inserted": inserted_count,
|
||
|
|
"updated": updated_count,
|
||
|
|
"timestamp": datetime.now().isoformat()
|
||
|
|
}
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"❌ e-conomic accounts sync failed: {e}", exc_info=True)
|
||
|
|
return {
|
||
|
|
"success": False,
|
||
|
|
"error": str(e),
|
||
|
|
"timestamp": datetime.now().isoformat()
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
# Allow running this job manually for testing
|
||
|
|
import asyncio
|
||
|
|
result = asyncio.run(sync_economic_accounts())
|
||
|
|
print(f"Sync result: {result}")
|