61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
import uuid
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.audit import service as audit
|
|
from app.db.session import set_space_context
|
|
from app.errors import conflict, forbidden, not_found
|
|
from app.identity.models import User
|
|
from app.spaces.models import FinancialSpace, Membership
|
|
|
|
|
|
def create_space(db: Session, *, user: User, name: str) -> FinancialSpace:
|
|
space = FinancialSpace(name=name)
|
|
db.add(space)
|
|
db.flush()
|
|
set_space_context(db, space.id)
|
|
db.add(Membership(space_id=space.id, user_id=user.id, role="owner"))
|
|
from app.ledger.savings import ensure_savings_resources
|
|
|
|
ensure_savings_resources(db, space_id=space.id)
|
|
audit.record(db, event_type="space.created", space_id=space.id, user_id=user.id)
|
|
return space
|
|
|
|
|
|
def get_membership(db: Session, *, space_id: uuid.UUID, user_id: uuid.UUID) -> Membership:
|
|
membership = db.query(Membership).filter_by(space_id=space_id, user_id=user_id).first()
|
|
if membership is None:
|
|
raise not_found("SPACE_NOT_FOUND", "Financial space not found")
|
|
return membership
|
|
|
|
|
|
def get_space_for_member(
|
|
db: Session, *, space_id: uuid.UUID, user: User
|
|
) -> tuple[FinancialSpace, Membership]:
|
|
space = db.get(FinancialSpace, space_id)
|
|
if space is None:
|
|
raise not_found("SPACE_NOT_FOUND", "Financial space not found")
|
|
membership = get_membership(db, space_id=space_id, user_id=user.id)
|
|
if space.status == "blocked":
|
|
raise conflict(
|
|
"SPACE_BLOCKED",
|
|
"Financial space is blocked pending deletion",
|
|
)
|
|
return space, membership
|
|
|
|
|
|
def require_owner(membership: Membership) -> None:
|
|
if membership.role != "owner":
|
|
raise forbidden("SPACE_OWNER_REQUIRED", "Owner role required")
|
|
|
|
|
|
def list_spaces_for_user(db: Session, *, user: User) -> list[tuple[FinancialSpace, Membership]]:
|
|
rows = (
|
|
db.query(FinancialSpace, Membership)
|
|
.join(Membership, Membership.space_id == FinancialSpace.id)
|
|
.filter(Membership.user_id == user.id)
|
|
.order_by(FinancialSpace.created_at)
|
|
.all()
|
|
)
|
|
return [(space, membership) for space, membership in rows]
|