From d5226a5599206ece56235b2a64e48ba136a14cb2 Mon Sep 17 00:00:00 2001
From: patrick-motsch
Date: Wed, 4 Feb 2026 22:34:41 +0100
Subject: [PATCH] boot running without errors
---
modules/interfaces/interfaceDbBilling.py | 43 +++++---
modules/routes/routeBilling.py | 98 ++++++++-----------
.../serviceBilling/mainServiceBilling.py | 13 +--
3 files changed, 77 insertions(+), 77 deletions(-)
diff --git a/modules/interfaces/interfaceDbBilling.py b/modules/interfaces/interfaceDbBilling.py
index ebbe3ae5..141fc118 100644
--- a/modules/interfaces/interfaceDbBilling.py
+++ b/modules/interfaces/interfaceDbBilling.py
@@ -92,11 +92,11 @@ class BillingObjects:
def _initializeDatabase(self):
"""Initialize database connection."""
self.db = DatabaseConnector(
- databaseName=BILLING_DATABASE,
- host=APP_CONFIG.get('Database_Host', 'localhost'),
- port=int(APP_CONFIG.get('Database_Port', '5432')),
- user=APP_CONFIG.get('Database_User', 'admin'),
- password=APP_CONFIG.get('Database_Password', 'admin')
+ dbDatabase=BILLING_DATABASE,
+ dbHost=APP_CONFIG.get('DB_HOST', 'localhost'),
+ dbPort=int(APP_CONFIG.get('DB_PORT', '5432')),
+ dbUser=APP_CONFIG.get('DB_USER'),
+ dbPassword=APP_CONFIG.get('DB_PASSWORD_SECRET')
)
def setUserContext(self, currentUser: User, mandateId: str = None):
@@ -128,7 +128,7 @@ class BillingObjects:
try:
results = self.db.getRecordset(
BillingSettings,
- filterDict={"mandateId": mandateId}
+ recordFilter={"mandateId": mandateId}
)
return results[0] if results else None
except Exception as e:
@@ -200,7 +200,7 @@ class BillingObjects:
try:
results = self.db.getRecordset(
BillingAccount,
- filterDict={"id": accountId}
+ recordFilter={"id": accountId}
)
return results[0] if results else None
except Exception as e:
@@ -220,7 +220,7 @@ class BillingObjects:
try:
results = self.db.getRecordset(
BillingAccount,
- filterDict={
+ recordFilter={
"mandateId": mandateId,
"accountType": AccountTypeEnum.MANDATE.value
}
@@ -244,7 +244,7 @@ class BillingObjects:
try:
results = self.db.getRecordset(
BillingAccount,
- filterDict={
+ recordFilter={
"mandateId": mandateId,
"userId": userId,
"accountType": AccountTypeEnum.USER.value
@@ -255,6 +255,25 @@ class BillingObjects:
logger.error(f"Error getting user account: {e}")
return None
+ def getAccountsByMandate(self, mandateId: str) -> List[Dict[str, Any]]:
+ """
+ Get all billing accounts for a mandate.
+
+ Args:
+ mandateId: Mandate ID
+
+ Returns:
+ List of BillingAccount dicts
+ """
+ try:
+ return self.db.getRecordset(
+ BillingAccount,
+ recordFilter={"mandateId": mandateId}
+ )
+ except Exception as e:
+ logger.error(f"Error getting accounts for mandate: {e}")
+ return []
+
def createAccount(self, account: BillingAccount) -> Dict[str, Any]:
"""
Create a new billing account.
@@ -405,7 +424,7 @@ class BillingObjects:
"""
try:
filterDict = {"accountId": accountId}
- results = self.db.getRecordset(BillingTransaction, filterDict=filterDict)
+ results = self.db.getRecordset(BillingTransaction, recordFilter=filterDict)
# Apply date filters if provided
if startDate or endDate:
@@ -442,7 +461,7 @@ class BillingObjects:
List of transaction dicts
"""
# Get all accounts for mandate
- accounts = self.db.getRecordset(BillingAccount, filterDict={"mandateId": mandateId})
+ accounts = self.db.getRecordset(BillingAccount, recordFilter={"mandateId": mandateId})
allTransactions = []
for account in accounts:
@@ -616,7 +635,7 @@ class BillingObjects:
"periodType": periodType.value
}
- results = self.db.getRecordset(UsageStatistics, filterDict=filterDict)
+ results = self.db.getRecordset(UsageStatistics, recordFilter=filterDict)
# Filter by year
filtered = [s for s in results if s.get("periodStart") and s["periodStart"].year == year]
diff --git a/modules/routes/routeBilling.py b/modules/routes/routeBilling.py
index c191e793..e3698509 100644
--- a/modules/routes/routeBilling.py
+++ b/modules/routes/routeBilling.py
@@ -136,11 +136,11 @@ async def getBalance(
raise HTTPException(status_code=500, detail=str(e))
-@router.get("/balance/{mandateId}", response_model=BillingBalanceResponse)
+@router.get("/balance/{targetMandateId}", response_model=BillingBalanceResponse)
@limiter.limit("60/minute")
async def getBalanceForMandate(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
+ targetMandateId: str = Path(..., description="Mandate ID"),
ctx: RequestContext = Depends(getRequestContext)
):
"""
@@ -149,7 +149,7 @@ async def getBalanceForMandate(
try:
billingService = getBillingService(
ctx.currentUser,
- mandateId,
+ targetMandateId,
featureCode="billing"
)
@@ -158,12 +158,12 @@ async def getBalanceForMandate(
# Get mandate name from app interface
from modules.interfaces.interfaceDbApp import getInterface as getAppInterface
- appInterface = getAppInterface(ctx.currentUser, mandateId=mandateId)
- mandate = appInterface.getMandate(mandateId)
+ appInterface = getAppInterface(ctx.currentUser, mandateId=targetMandateId)
+ mandate = appInterface.getMandate(targetMandateId)
mandateName = mandate.get("name", "") if mandate else ""
return BillingBalanceResponse(
- mandateId=mandateId,
+ mandateId=targetMandateId,
mandateName=mandateName,
billingModel=checkResult.billingModel or BillingModelEnum.UNLIMITED,
balance=checkResult.currentBalance or 0.0,
@@ -173,7 +173,7 @@ async def getBalanceForMandate(
)
except Exception as e:
- logger.error(f"Error getting billing balance for mandate {mandateId}: {e}")
+ logger.error(f"Error getting billing balance for mandate {targetMandateId}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@@ -332,20 +332,20 @@ async def getAllowedProviders(
# Admin Endpoints
# =============================================================================
-@router.get("/admin/settings/{mandateId}", response_model=Dict[str, Any])
+@router.get("/admin/settings/{targetMandateId}", response_model=Dict[str, Any])
@limiter.limit("30/minute")
-@requireSysAdmin
async def getSettingsAdmin(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
- ctx: RequestContext = Depends(getRequestContext)
+ targetMandateId: str = Path(..., description="Mandate ID"),
+ ctx: RequestContext = Depends(getRequestContext),
+ _admin = Depends(requireSysAdmin)
):
"""
Get billing settings for a mandate (SysAdmin only).
"""
try:
- billingInterface = getBillingInterface(ctx.currentUser, mandateId)
- settings = billingInterface.getSettings(mandateId)
+ billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
+ settings = billingInterface.getSettings(targetMandateId)
if not settings:
raise HTTPException(status_code=404, detail="Billing settings not found")
@@ -359,21 +359,21 @@ async def getSettingsAdmin(
raise HTTPException(status_code=500, detail=str(e))
-@router.post("/admin/settings/{mandateId}", response_model=Dict[str, Any])
+@router.post("/admin/settings/{targetMandateId}", response_model=Dict[str, Any])
@limiter.limit("10/minute")
-@requireSysAdmin
async def createOrUpdateSettings(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
+ targetMandateId: str = Path(..., description="Mandate ID"),
settingsUpdate: BillingSettingsUpdate = Body(...),
- ctx: RequestContext = Depends(getRequestContext)
+ ctx: RequestContext = Depends(getRequestContext),
+ _admin = Depends(requireSysAdmin)
):
"""
Create or update billing settings for a mandate (SysAdmin only).
"""
try:
- billingInterface = getBillingInterface(ctx.currentUser, mandateId)
- existingSettings = billingInterface.getSettings(mandateId)
+ billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
+ existingSettings = billingInterface.getSettings(targetMandateId)
if existingSettings:
# Update existing settings
@@ -387,7 +387,7 @@ async def createOrUpdateSettings(
from modules.datamodels.datamodelBilling import BillingSettings
newSettings = BillingSettings(
- mandateId=mandateId,
+ mandateId=targetMandateId,
billingModel=settingsUpdate.billingModel or BillingModelEnum.UNLIMITED,
defaultUserCredit=settingsUpdate.defaultUserCredit or 10.0,
warningThresholdPercent=settingsUpdate.warningThresholdPercent or 10.0,
@@ -406,14 +406,14 @@ async def createOrUpdateSettings(
raise HTTPException(status_code=500, detail=str(e))
-@router.post("/admin/credit/{mandateId}", response_model=Dict[str, Any])
+@router.post("/admin/credit/{targetMandateId}", response_model=Dict[str, Any])
@limiter.limit("10/minute")
-@requireSysAdmin
async def addCredit(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
+ targetMandateId: str = Path(..., description="Mandate ID"),
creditRequest: CreditAddRequest = Body(...),
- ctx: RequestContext = Depends(getRequestContext)
+ ctx: RequestContext = Depends(getRequestContext),
+ _admin = Depends(requireSysAdmin)
):
"""
Add credit to a billing account (SysAdmin only).
@@ -421,8 +421,8 @@ async def addCredit(
"""
try:
# Get settings to determine billing model
- billingInterface = getBillingInterface(ctx.currentUser, mandateId)
- settings = billingInterface.getSettings(mandateId)
+ billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
+ settings = billingInterface.getSettings(targetMandateId)
if not settings:
raise HTTPException(status_code=404, detail="Billing settings not found for this mandate")
@@ -436,13 +436,13 @@ async def addCredit(
# Create user-level account if needed and add credit
account = billingInterface.getOrCreateUserAccount(
- mandateId,
+ targetMandateId,
creditRequest.userId,
initialBalance=0.0
)
elif billingModel in [BillingModelEnum.PREPAY_MANDATE, BillingModelEnum.CREDIT_POSTPAY]:
# Create mandate-level account if needed and add credit
- account = billingInterface.getOrCreateMandateAccount(mandateId, initialBalance=0.0)
+ account = billingInterface.getOrCreateMandateAccount(targetMandateId, initialBalance=0.0)
else:
raise HTTPException(status_code=400, detail=f"Cannot add credit to {billingModel.value} billing model")
@@ -459,7 +459,7 @@ async def addCredit(
result = billingInterface.createTransaction(transaction)
- logger.info(f"Added {creditRequest.amount} CHF credit to account {account['id']} in mandate {mandateId}")
+ logger.info(f"Added {creditRequest.amount} CHF credit to account {account['id']} in mandate {targetMandateId}")
return result
@@ -470,34 +470,22 @@ async def addCredit(
raise HTTPException(status_code=500, detail=str(e))
-@router.get("/admin/accounts/{mandateId}", response_model=List[AccountSummary])
+@router.get("/admin/accounts/{targetMandateId}", response_model=List[AccountSummary])
@limiter.limit("30/minute")
-@requireSysAdmin
async def getAccounts(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
- ctx: RequestContext = Depends(getRequestContext)
+ targetMandateId: str = Path(..., description="Mandate ID"),
+ ctx: RequestContext = Depends(getRequestContext),
+ _admin = Depends(requireSysAdmin)
):
"""
Get all billing accounts for a mandate (SysAdmin only).
"""
try:
- billingInterface = getBillingInterface(ctx.currentUser, mandateId)
+ billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
- # Get all accounts for this mandate
- from modules.connectors.connectorDbPostgre import DatabaseConnector
- from modules.shared.configuration import APP_CONFIG
- from modules.datamodels.datamodelBilling import BillingAccount
-
- db = DatabaseConnector(
- databaseName="poweron_billing",
- host=APP_CONFIG.get('Database_Host', 'localhost'),
- port=int(APP_CONFIG.get('Database_Port', '5432')),
- user=APP_CONFIG.get('Database_User', 'admin'),
- password=APP_CONFIG.get('Database_Password', 'admin')
- )
-
- accounts = db.getRecordset(BillingAccount, filterDict={"mandateId": mandateId})
+ # Get all accounts for this mandate via interface
+ accounts = billingInterface.getAccountsByMandate(targetMandateId)
result = []
for acc in accounts:
@@ -519,21 +507,21 @@ async def getAccounts(
raise HTTPException(status_code=500, detail=str(e))
-@router.get("/admin/transactions/{mandateId}", response_model=List[TransactionResponse])
+@router.get("/admin/transactions/{targetMandateId}", response_model=List[TransactionResponse])
@limiter.limit("30/minute")
-@requireSysAdmin
async def getTransactionsAdmin(
request: Request,
- mandateId: str = Path(..., description="Mandate ID"),
+ targetMandateId: str = Path(..., description="Mandate ID"),
limit: int = Query(default=100, ge=1, le=1000),
- ctx: RequestContext = Depends(getRequestContext)
+ ctx: RequestContext = Depends(getRequestContext),
+ _admin = Depends(requireSysAdmin)
):
"""
Get all transactions for a mandate (SysAdmin only).
"""
try:
- billingInterface = getBillingInterface(ctx.currentUser, mandateId)
- transactions = billingInterface.getTransactionsByMandate(mandateId, limit=limit)
+ billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
+ transactions = billingInterface.getTransactionsByMandate(targetMandateId, limit=limit)
result = []
for t in transactions:
@@ -553,5 +541,5 @@ async def getTransactionsAdmin(
return result
except Exception as e:
- logger.error(f"Error getting billing transactions for mandate {mandateId}: {e}")
+ logger.error(f"Error getting billing transactions for mandate {targetMandateId}: {e}")
raise HTTPException(status_code=500, detail=str(e))
diff --git a/modules/services/serviceBilling/mainServiceBilling.py b/modules/services/serviceBilling/mainServiceBilling.py
index 709ab61a..c7a08a1c 100644
--- a/modules/services/serviceBilling/mainServiceBilling.py
+++ b/modules/services/serviceBilling/mainServiceBilling.py
@@ -255,17 +255,10 @@ class BillingService:
try:
from modules.security.rbac import RbacClass
from modules.datamodels.datamodelRbac import AccessRuleContext
- from modules.connectors.connectorDbPostgre import DatabaseConnector
- from modules.shared.configuration import APP_CONFIG
+ from modules.security.rootAccess import getRootDbAppConnector
- # Get database connectors
- dbApp = DatabaseConnector(
- databaseName="poweron_app",
- host=APP_CONFIG.get('Database_Host', 'localhost'),
- port=int(APP_CONFIG.get('Database_Port', '5432')),
- user=APP_CONFIG.get('Database_User', 'admin'),
- password=APP_CONFIG.get('Database_Password', 'admin')
- )
+ # Get database connector via established pattern
+ dbApp = getRootDbAppConnector()
rbac = RbacClass(dbApp, dbApp)
resourceKey = f"resource.aicore.{provider}"