fixed database issue subscriptions

This commit is contained in:
ValueOn AG 2026-03-31 01:51:08 +02:00
parent 350c699473
commit ef39d01e16
4 changed files with 60 additions and 22 deletions

View file

@ -88,12 +88,15 @@ class CSRFMiddleware(BaseHTTPMiddleware):
content={"detail": "Invalid CSRF token format"}
)
# Additional CSRF validation could be added here:
# - Check token against session
# - Validate token expiration
# - Verify token origin
return await call_next(request)
try:
return await call_next(request)
except Exception as exc:
logger.error("Unhandled exception in %s %s: %s", request.method, request.url.path, exc)
from fastapi.responses import JSONResponse
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)
def _is_valid_csrf_token(self, token: str) -> bool:
"""

View file

@ -1728,8 +1728,10 @@ class AppObjects:
self.db.recordDelete(UserMandate, um.get("id"))
logger.info(f"Cascade: deleted {len(memberships)} UserMandates for mandate {mandateId}")
# 3. Cancel Stripe subscriptions + delete MandateSubscription records
subs = self.db.getRecordset(MandateSubscription, recordFilter={"mandateId": mandateId})
# 3. Cancel Stripe subscriptions + delete MandateSubscription records (poweron_billing)
from modules.interfaces.interfaceDbSubscription import _getRootInterface as _getSubRoot
subInterface = _getSubRoot()
subs = subInterface.listForMandate(mandateId)
for sub in subs:
subId = sub.get("id")
stripeSubId = sub.get("stripeSubscriptionId")
@ -1741,20 +1743,21 @@ class AppObjects:
logger.info(f"Cancelled Stripe subscription {stripeSubId} for mandate {mandateId}")
except Exception as e:
logger.warning(f"Failed to cancel Stripe sub {stripeSubId}: {e}")
self.db.recordDelete(MandateSubscription, subId)
subInterface.db.recordDelete(MandateSubscription, subId)
logger.info(f"Cascade: deleted {len(subs)} subscriptions for mandate {mandateId}")
# 3b. Delete Billing data
billingTxs = self.db.getRecordset(BillingTransaction, recordFilter={"mandateId": mandateId}) if hasattr(BillingTransaction, '__table_name__') else []
billingAccounts = self.db.getRecordset(BillingAccount, recordFilter={"mandateId": mandateId})
# 3b. Delete Billing data (poweron_billing)
from modules.interfaces.interfaceDbBilling import _getRootInterface as _getBillingRoot
billingDb = _getBillingRoot().db
billingAccounts = billingDb.getRecordset(BillingAccount, recordFilter={"mandateId": mandateId})
for acc in billingAccounts:
accTxs = self.db.getRecordset(BillingTransaction, recordFilter={"accountId": acc.get("id")})
accTxs = billingDb.getRecordset(BillingTransaction, recordFilter={"accountId": acc.get("id")})
for tx in accTxs:
self.db.recordDelete(BillingTransaction, tx.get("id"))
self.db.recordDelete(BillingAccount, acc.get("id"))
billingSettings = self.db.getRecordset(BillingSettings, recordFilter={"mandateId": mandateId})
billingDb.recordDelete(BillingTransaction, tx.get("id"))
billingDb.recordDelete(BillingAccount, acc.get("id"))
billingSettings = billingDb.getRecordset(BillingSettings, recordFilter={"mandateId": mandateId})
for bs in billingSettings:
self.db.recordDelete(BillingSettings, bs.get("id"))
billingDb.recordDelete(BillingSettings, bs.get("id"))
if billingAccounts or billingSettings:
logger.info(f"Cascade: deleted billing data for mandate {mandateId}")

View file

@ -319,6 +319,35 @@ def create_mandate(
f"Could not create default billing settings for mandate {newMandate.id}: {billingErr}"
)
try:
from modules.datamodels.datamodelSubscription import (
MandateSubscription, SubscriptionStatusEnum, BUILTIN_PLANS,
)
from modules.interfaces.interfaceDbSubscription import _getRootInterface as _getSubRoot
from datetime import datetime, timezone, timedelta
planKey = mandateData.get("planKey", "TRIAL_7D")
plan = BUILTIN_PLANS.get(planKey)
if plan:
now = datetime.now(timezone.utc)
targetStatus = SubscriptionStatusEnum.TRIALING if plan.trialDays else SubscriptionStatusEnum.ACTIVE
sub = MandateSubscription(
mandateId=str(newMandate.id),
planKey=planKey,
status=targetStatus,
recurring=plan.autoRenew and not plan.trialDays,
startedAt=now,
currentPeriodStart=now,
)
if plan.trialDays:
sub.trialEndsAt = now + timedelta(days=plan.trialDays)
sub.currentPeriodEnd = now + timedelta(days=plan.trialDays)
subInterface = _getSubRoot()
subInterface.createSubscription(sub)
logger.info(f"Created {targetStatus.value} subscription ({planKey}) for mandate {newMandate.id}")
except Exception as subErr:
logger.error(f"Failed to create subscription for mandate {newMandate.id}: {subErr}")
logger.info(f"Mandate {newMandate.id} created by SysAdmin {currentUser.id}")
return newMandate

View file

@ -187,9 +187,12 @@ def getSubscriptionInfo(
"budgetAiCHF": None,
}
from modules.datamodels.datamodelSubscription import MandateSubscription, BUILTIN_PLANS
subs = db.getRecordset(MandateSubscription, recordFilter={"mandateId": mandateId})
if not subs:
from modules.datamodels.datamodelSubscription import BUILTIN_PLANS
from modules.interfaces.interfaceDbSubscription import _getRootInterface as _getSubRoot
subInterface = _getSubRoot()
allSubs = subInterface.listForMandate(mandateId)
if not allSubs:
return {
"plan": None,
"maxDataVolumeMB": None,
@ -197,7 +200,7 @@ def getSubscriptionInfo(
"budgetAiCHF": None,
}
sub = subs[0]
sub = allSubs[0]
plan = BUILTIN_PLANS.get(sub.get("planKey"))
currentInstances = db.getRecordset(FeatureInstance, recordFilter={"mandateId": mandateId})