bmc_hub/app/jobs/invoice_error_finder_sync.py
Christian 128a2b83d0 feat(invoice_error_finder): add invoice error finder module
- Detect missing invoice lines, open orders not invoiced, quantity drops, price changes
- Import e-conomic invoices and Simply CRM sales orders
- Dashboard and issues UI with sag/ordre-draft actions
- Scheduled daily sync job at 05:00
- Add invoice_error_finder permissions
2026-07-10 07:08:49 +02:00

85 lines
3.1 KiB
Python

"""
Scheduled sync job for Invoice Error Finder.
Runs daily after subscription processing to import e-conomic and Simply data
and re-run anomaly detection.
"""
import logging
from app.modules.invoice_error_finder.services.economic_import_service import EconomicImportService
from app.modules.invoice_error_finder.services.simply_import_service import SimplyImportService
from app.modules.invoice_error_finder.services.detection_service import DetectionService
logger = logging.getLogger(__name__)
async def run_invoice_error_finder_sync() -> dict:
"""
Daily scheduled job:
1. Import e-conomic invoices (last 13 months).
2. Import open Simply CRM sales orders.
3. Re-import Simply subscription staging via existing endpoint.
4. Run anomaly detection for current month.
"""
logger.info("🔄 Starting scheduled Invoice Error Finder sync")
economic_result = {"records_imported": 0, "records_failed": 0}
simply_result = {"records_imported": 0, "records_failed": 0}
staging_result = {"records_imported": 0, "records_failed": 0}
detection_counts = {}
errors = []
try:
economic_service = EconomicImportService()
economic_result = await economic_service.import_invoices(
triggered_by_user_id=None,
is_scheduled=True,
)
except Exception as exc:
logger.error("❌ Scheduled e-conomic import failed: %s", exc, exc_info=True)
errors.append(f"economic: {exc}")
try:
simply_service = SimplyImportService()
simply_result = await simply_service.import_sales_orders(
triggered_by_user_id=None,
is_scheduled=True,
)
except Exception as exc:
logger.error("❌ Scheduled Simply sales order import failed: %s", exc, exc_info=True)
errors.append(f"simply: {exc}")
# Refresh Simply subscription staging by calling the existing import function directly
try:
from app.subscriptions.backend.router import import_simply_subscriptions_to_staging
staging_data = await import_simply_subscriptions_to_staging()
staging_result = {
"records_imported": staging_data.get("imported", 0),
"records_failed": staging_data.get("errors", 0),
}
except Exception as exc:
logger.error("❌ Scheduled Simply subscription staging import failed: %s", exc, exc_info=True)
errors.append(f"staging: {exc}")
try:
detection_service = DetectionService()
detection_counts = detection_service.analyze()
except Exception as exc:
logger.error("❌ Scheduled detection failed: %s", exc, exc_info=True)
errors.append(f"detection: {exc}")
result = {
"economic": economic_result,
"simply": simply_result,
"staging": staging_result,
"detection": detection_counts,
"errors": errors,
}
if errors:
logger.warning("⚠️ Invoice Error Finder sync completed with errors: %s", errors)
else:
logger.info("✅ Invoice Error Finder sync completed successfully: %s", result)
return result