boot running without errors

This commit is contained in:
patrick-motsch 2026-02-04 22:34:41 +01:00
parent fd923b89b8
commit d5226a5599
3 changed files with 77 additions and 77 deletions

View file

@ -92,11 +92,11 @@ class BillingObjects:
def _initializeDatabase(self): def _initializeDatabase(self):
"""Initialize database connection.""" """Initialize database connection."""
self.db = DatabaseConnector( self.db = DatabaseConnector(
databaseName=BILLING_DATABASE, dbDatabase=BILLING_DATABASE,
host=APP_CONFIG.get('Database_Host', 'localhost'), dbHost=APP_CONFIG.get('DB_HOST', 'localhost'),
port=int(APP_CONFIG.get('Database_Port', '5432')), dbPort=int(APP_CONFIG.get('DB_PORT', '5432')),
user=APP_CONFIG.get('Database_User', 'admin'), dbUser=APP_CONFIG.get('DB_USER'),
password=APP_CONFIG.get('Database_Password', 'admin') dbPassword=APP_CONFIG.get('DB_PASSWORD_SECRET')
) )
def setUserContext(self, currentUser: User, mandateId: str = None): def setUserContext(self, currentUser: User, mandateId: str = None):
@ -128,7 +128,7 @@ class BillingObjects:
try: try:
results = self.db.getRecordset( results = self.db.getRecordset(
BillingSettings, BillingSettings,
filterDict={"mandateId": mandateId} recordFilter={"mandateId": mandateId}
) )
return results[0] if results else None return results[0] if results else None
except Exception as e: except Exception as e:
@ -200,7 +200,7 @@ class BillingObjects:
try: try:
results = self.db.getRecordset( results = self.db.getRecordset(
BillingAccount, BillingAccount,
filterDict={"id": accountId} recordFilter={"id": accountId}
) )
return results[0] if results else None return results[0] if results else None
except Exception as e: except Exception as e:
@ -220,7 +220,7 @@ class BillingObjects:
try: try:
results = self.db.getRecordset( results = self.db.getRecordset(
BillingAccount, BillingAccount,
filterDict={ recordFilter={
"mandateId": mandateId, "mandateId": mandateId,
"accountType": AccountTypeEnum.MANDATE.value "accountType": AccountTypeEnum.MANDATE.value
} }
@ -244,7 +244,7 @@ class BillingObjects:
try: try:
results = self.db.getRecordset( results = self.db.getRecordset(
BillingAccount, BillingAccount,
filterDict={ recordFilter={
"mandateId": mandateId, "mandateId": mandateId,
"userId": userId, "userId": userId,
"accountType": AccountTypeEnum.USER.value "accountType": AccountTypeEnum.USER.value
@ -255,6 +255,25 @@ class BillingObjects:
logger.error(f"Error getting user account: {e}") logger.error(f"Error getting user account: {e}")
return None 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]: def createAccount(self, account: BillingAccount) -> Dict[str, Any]:
""" """
Create a new billing account. Create a new billing account.
@ -405,7 +424,7 @@ class BillingObjects:
""" """
try: try:
filterDict = {"accountId": accountId} filterDict = {"accountId": accountId}
results = self.db.getRecordset(BillingTransaction, filterDict=filterDict) results = self.db.getRecordset(BillingTransaction, recordFilter=filterDict)
# Apply date filters if provided # Apply date filters if provided
if startDate or endDate: if startDate or endDate:
@ -442,7 +461,7 @@ class BillingObjects:
List of transaction dicts List of transaction dicts
""" """
# Get all accounts for mandate # Get all accounts for mandate
accounts = self.db.getRecordset(BillingAccount, filterDict={"mandateId": mandateId}) accounts = self.db.getRecordset(BillingAccount, recordFilter={"mandateId": mandateId})
allTransactions = [] allTransactions = []
for account in accounts: for account in accounts:
@ -616,7 +635,7 @@ class BillingObjects:
"periodType": periodType.value "periodType": periodType.value
} }
results = self.db.getRecordset(UsageStatistics, filterDict=filterDict) results = self.db.getRecordset(UsageStatistics, recordFilter=filterDict)
# Filter by year # Filter by year
filtered = [s for s in results if s.get("periodStart") and s["periodStart"].year == year] filtered = [s for s in results if s.get("periodStart") and s["periodStart"].year == year]

View file

@ -136,11 +136,11 @@ async def getBalance(
raise HTTPException(status_code=500, detail=str(e)) 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") @limiter.limit("60/minute")
async def getBalanceForMandate( async def getBalanceForMandate(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
ctx: RequestContext = Depends(getRequestContext) ctx: RequestContext = Depends(getRequestContext)
): ):
""" """
@ -149,7 +149,7 @@ async def getBalanceForMandate(
try: try:
billingService = getBillingService( billingService = getBillingService(
ctx.currentUser, ctx.currentUser,
mandateId, targetMandateId,
featureCode="billing" featureCode="billing"
) )
@ -158,12 +158,12 @@ async def getBalanceForMandate(
# Get mandate name from app interface # Get mandate name from app interface
from modules.interfaces.interfaceDbApp import getInterface as getAppInterface from modules.interfaces.interfaceDbApp import getInterface as getAppInterface
appInterface = getAppInterface(ctx.currentUser, mandateId=mandateId) appInterface = getAppInterface(ctx.currentUser, mandateId=targetMandateId)
mandate = appInterface.getMandate(mandateId) mandate = appInterface.getMandate(targetMandateId)
mandateName = mandate.get("name", "") if mandate else "" mandateName = mandate.get("name", "") if mandate else ""
return BillingBalanceResponse( return BillingBalanceResponse(
mandateId=mandateId, mandateId=targetMandateId,
mandateName=mandateName, mandateName=mandateName,
billingModel=checkResult.billingModel or BillingModelEnum.UNLIMITED, billingModel=checkResult.billingModel or BillingModelEnum.UNLIMITED,
balance=checkResult.currentBalance or 0.0, balance=checkResult.currentBalance or 0.0,
@ -173,7 +173,7 @@ async def getBalanceForMandate(
) )
except Exception as e: 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)) raise HTTPException(status_code=500, detail=str(e))
@ -332,20 +332,20 @@ async def getAllowedProviders(
# Admin Endpoints # 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") @limiter.limit("30/minute")
@requireSysAdmin
async def getSettingsAdmin( async def getSettingsAdmin(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
ctx: RequestContext = Depends(getRequestContext) ctx: RequestContext = Depends(getRequestContext),
_admin = Depends(requireSysAdmin)
): ):
""" """
Get billing settings for a mandate (SysAdmin only). Get billing settings for a mandate (SysAdmin only).
""" """
try: try:
billingInterface = getBillingInterface(ctx.currentUser, mandateId) billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
settings = billingInterface.getSettings(mandateId) settings = billingInterface.getSettings(targetMandateId)
if not settings: if not settings:
raise HTTPException(status_code=404, detail="Billing settings not found") 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)) 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") @limiter.limit("10/minute")
@requireSysAdmin
async def createOrUpdateSettings( async def createOrUpdateSettings(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
settingsUpdate: BillingSettingsUpdate = Body(...), settingsUpdate: BillingSettingsUpdate = Body(...),
ctx: RequestContext = Depends(getRequestContext) ctx: RequestContext = Depends(getRequestContext),
_admin = Depends(requireSysAdmin)
): ):
""" """
Create or update billing settings for a mandate (SysAdmin only). Create or update billing settings for a mandate (SysAdmin only).
""" """
try: try:
billingInterface = getBillingInterface(ctx.currentUser, mandateId) billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
existingSettings = billingInterface.getSettings(mandateId) existingSettings = billingInterface.getSettings(targetMandateId)
if existingSettings: if existingSettings:
# Update existing settings # Update existing settings
@ -387,7 +387,7 @@ async def createOrUpdateSettings(
from modules.datamodels.datamodelBilling import BillingSettings from modules.datamodels.datamodelBilling import BillingSettings
newSettings = BillingSettings( newSettings = BillingSettings(
mandateId=mandateId, mandateId=targetMandateId,
billingModel=settingsUpdate.billingModel or BillingModelEnum.UNLIMITED, billingModel=settingsUpdate.billingModel or BillingModelEnum.UNLIMITED,
defaultUserCredit=settingsUpdate.defaultUserCredit or 10.0, defaultUserCredit=settingsUpdate.defaultUserCredit or 10.0,
warningThresholdPercent=settingsUpdate.warningThresholdPercent or 10.0, warningThresholdPercent=settingsUpdate.warningThresholdPercent or 10.0,
@ -406,14 +406,14 @@ async def createOrUpdateSettings(
raise HTTPException(status_code=500, detail=str(e)) 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") @limiter.limit("10/minute")
@requireSysAdmin
async def addCredit( async def addCredit(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
creditRequest: CreditAddRequest = Body(...), creditRequest: CreditAddRequest = Body(...),
ctx: RequestContext = Depends(getRequestContext) ctx: RequestContext = Depends(getRequestContext),
_admin = Depends(requireSysAdmin)
): ):
""" """
Add credit to a billing account (SysAdmin only). Add credit to a billing account (SysAdmin only).
@ -421,8 +421,8 @@ async def addCredit(
""" """
try: try:
# Get settings to determine billing model # Get settings to determine billing model
billingInterface = getBillingInterface(ctx.currentUser, mandateId) billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
settings = billingInterface.getSettings(mandateId) settings = billingInterface.getSettings(targetMandateId)
if not settings: if not settings:
raise HTTPException(status_code=404, detail="Billing settings not found for this mandate") 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 # Create user-level account if needed and add credit
account = billingInterface.getOrCreateUserAccount( account = billingInterface.getOrCreateUserAccount(
mandateId, targetMandateId,
creditRequest.userId, creditRequest.userId,
initialBalance=0.0 initialBalance=0.0
) )
elif billingModel in [BillingModelEnum.PREPAY_MANDATE, BillingModelEnum.CREDIT_POSTPAY]: elif billingModel in [BillingModelEnum.PREPAY_MANDATE, BillingModelEnum.CREDIT_POSTPAY]:
# Create mandate-level account if needed and add credit # Create mandate-level account if needed and add credit
account = billingInterface.getOrCreateMandateAccount(mandateId, initialBalance=0.0) account = billingInterface.getOrCreateMandateAccount(targetMandateId, initialBalance=0.0)
else: else:
raise HTTPException(status_code=400, detail=f"Cannot add credit to {billingModel.value} billing model") 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) 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 return result
@ -470,34 +470,22 @@ async def addCredit(
raise HTTPException(status_code=500, detail=str(e)) 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") @limiter.limit("30/minute")
@requireSysAdmin
async def getAccounts( async def getAccounts(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
ctx: RequestContext = Depends(getRequestContext) ctx: RequestContext = Depends(getRequestContext),
_admin = Depends(requireSysAdmin)
): ):
""" """
Get all billing accounts for a mandate (SysAdmin only). Get all billing accounts for a mandate (SysAdmin only).
""" """
try: try:
billingInterface = getBillingInterface(ctx.currentUser, mandateId) billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
# Get all accounts for this mandate # Get all accounts for this mandate via interface
from modules.connectors.connectorDbPostgre import DatabaseConnector accounts = billingInterface.getAccountsByMandate(targetMandateId)
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})
result = [] result = []
for acc in accounts: for acc in accounts:
@ -519,21 +507,21 @@ async def getAccounts(
raise HTTPException(status_code=500, detail=str(e)) 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") @limiter.limit("30/minute")
@requireSysAdmin
async def getTransactionsAdmin( async def getTransactionsAdmin(
request: Request, request: Request,
mandateId: str = Path(..., description="Mandate ID"), targetMandateId: str = Path(..., description="Mandate ID"),
limit: int = Query(default=100, ge=1, le=1000), 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). Get all transactions for a mandate (SysAdmin only).
""" """
try: try:
billingInterface = getBillingInterface(ctx.currentUser, mandateId) billingInterface = getBillingInterface(ctx.currentUser, targetMandateId)
transactions = billingInterface.getTransactionsByMandate(mandateId, limit=limit) transactions = billingInterface.getTransactionsByMandate(targetMandateId, limit=limit)
result = [] result = []
for t in transactions: for t in transactions:
@ -553,5 +541,5 @@ async def getTransactionsAdmin(
return result return result
except Exception as e: 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)) raise HTTPException(status_code=500, detail=str(e))

View file

@ -255,17 +255,10 @@ class BillingService:
try: try:
from modules.security.rbac import RbacClass from modules.security.rbac import RbacClass
from modules.datamodels.datamodelRbac import AccessRuleContext from modules.datamodels.datamodelRbac import AccessRuleContext
from modules.connectors.connectorDbPostgre import DatabaseConnector from modules.security.rootAccess import getRootDbAppConnector
from modules.shared.configuration import APP_CONFIG
# Get database connectors # Get database connector via established pattern
dbApp = DatabaseConnector( dbApp = getRootDbAppConnector()
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')
)
rbac = RbacClass(dbApp, dbApp) rbac = RbacClass(dbApp, dbApp)
resourceKey = f"resource.aicore.{provider}" resourceKey = f"resource.aicore.{provider}"