gateway/modules/serviceCenter/services/serviceSubscription/enterpriseRenewalScheduler.py
2026-05-10 22:09:51 +02:00

89 lines
3.3 KiB
Python

# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""Enterprise subscription auto-renewal scheduler.
Runs daily via eventManager (APScheduler). Checks all enterprise subscriptions
with autoRenew=True whose period has ended and renews them automatically
(old -> EXPIRED, new -> ACTIVE with same duration and params, budget credit,
invoice email).
"""
import logging
from datetime import datetime, timezone
logger = logging.getLogger(__name__)
async def _runEnterpriseAutoRenewal() -> None:
"""Scheduled task: auto-renew enterprise subscriptions whose period has ended."""
try:
from modules.interfaces.interfaceDbSubscription import getRootInterface as _getSubRoot
from modules.datamodels.datamodelSubscription import SubscriptionStatusEnum
subIface = _getSubRoot()
allSubs = subIface.listAll([SubscriptionStatusEnum.ACTIVE])
nowTs = datetime.now(timezone.utc).timestamp()
renewed = 0
for sub in allSubs:
if not sub.get("isEnterprise"):
continue
if not sub.get("recurring"):
continue
periodEnd = sub.get("currentPeriodEnd")
if not periodEnd or periodEnd > nowTs:
continue
mandateId = sub["mandateId"]
subId = sub["id"]
periodStart = sub.get("currentPeriodStart") or sub.get("startedAt") or nowTs
periodDuration = periodEnd - periodStart
if periodDuration <= 0:
periodDuration = 30 * 86400
newEndDate = nowTs + periodDuration
try:
from modules.serviceCenter.services.serviceSubscription.mainServiceSubscription import (
getService as getSubscriptionService,
)
from modules.security.rootAccess import getRootUser
rootUser = getRootUser()
subService = getSubscriptionService(rootUser, mandateId)
subService.renewEnterprise(subId, newEndDate)
renewed += 1
logger.info(
"Auto-renewed enterprise subscription %s for mandate %s (new end: %s)",
subId, mandateId,
datetime.fromtimestamp(newEndDate, tz=timezone.utc).isoformat(),
)
except Exception as e:
logger.error(
"Auto-renewal failed for enterprise subscription %s mandate %s: %s",
subId, mandateId, e,
)
if renewed:
logger.info("Enterprise auto-renewal completed: %d subscription(s) renewed", renewed)
except Exception as e:
logger.error("Enterprise auto-renewal task failed: %s", e)
def registerEnterpriseRenewalScheduler() -> None:
"""Register the enterprise auto-renewal cron job (daily at 06:00 UTC)."""
try:
from modules.shared.eventManagement import eventManager
eventManager.registerCron(
jobId="enterprise_auto_renewal",
func=_runEnterpriseAutoRenewal,
cronKwargs={
"hour": "6",
"minute": "0",
},
)
logger.info("Enterprise auto-renewal scheduler registered (daily at 06:00 UTC)")
except Exception as e:
logger.error("Failed to register enterprise auto-renewal scheduler: %s", e)