Files
bambuddy/backend/app/services/finance_defaults.py
T
behrinml 010687eafd feat(finance): add cost center management and wallet transactions in the backend
- Introduced CostCenter and related models for managing print costs and budgets.
- Updated PrintArchive and PrintQueueItem models to include cost_center_id and estimated_cost.
- Implemented budget reservation logic in finance services to validate and manage print costs.
- Enhanced ArchiveService and BackgroundDispatchService to handle cost center information during print jobs.
- Added wallet transaction handling for print charges, including partial charges based on filament usage.
- Created finance billing and budget services to manage user wallets and budget reservations.
- Ensured user finance defaults are created upon user registration, including wallets and private cost centers.
- Updated print scheduler to validate budget before processing print jobs.
2026-06-24 10:52:26 +02:00

69 lines
2.3 KiB
Python

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from backend.app.models.finance import CostCenter, CostCenterMember, UserWallet
from backend.app.models.settings import Settings as AppSettingModel
from backend.app.models.user import User
from backend.app.schemas.settings import AppSettings as AppSettingsSchema
async def ensure_user_finance_defaults(db: AsyncSession, user: User) -> bool:
"""Ensure wallet and private cost center defaults exist for a user.
Returns True when database objects were created or changed.
"""
changed = False
wallet = (await db.execute(select(UserWallet).where(UserWallet.user_id == user.id))).scalar_one_or_none()
if wallet is None:
# Respect admin-configured currency if present, otherwise fall back to app default
default_currency = AppSettingsSchema().currency
result = await db.execute(select(AppSettingModel).where(AppSettingModel.key == "currency"))
setting = result.scalar_one_or_none()
currency = setting.value if setting and setting.value else default_currency
db.add(UserWallet(user_id=user.id, balance=0.0, currency=currency))
changed = True
private_center = (
(
await db.execute(
select(CostCenter)
.where(
CostCenter.is_private.is_(True),
CostCenter.owner_user_id == user.id,
)
.order_by(CostCenter.id.asc())
)
)
.scalars()
.first()
)
if private_center is None:
private_center = CostCenter(
name=user.username,
is_active=True,
is_private=True,
owner_user_id=user.id,
)
db.add(private_center)
await db.flush()
changed = True
elif private_center.name != user.username:
private_center.name = user.username
changed = True
membership = (
await db.execute(
select(CostCenterMember).where(
CostCenterMember.cost_center_id == private_center.id,
CostCenterMember.user_id == user.id,
)
)
).scalar_one_or_none()
if membership is None:
db.add(CostCenterMember(cost_center_id=private_center.id, user_id=user.id, can_print=True))
changed = True
return changed