104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
from collections import defaultdict
|
|
from typing import List
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from backend.modules.audit.models import AuditAction, AuditLog, AuditResourceType
|
|
from backend.modules.aws_accounts.models import AWSCredential, CustomerCredential
|
|
from backend.modules.customers.models import Customer
|
|
from backend.modules.users.models import User
|
|
|
|
|
|
async def list_customers(session: AsyncSession) -> List[Customer]:
|
|
customers = (await session.scalars(select(Customer))).all()
|
|
if not customers:
|
|
return customers
|
|
|
|
customer_ids = [c.id for c in customers]
|
|
|
|
cred_map: dict[int, list[str]] = defaultdict(list)
|
|
cred_rows = await session.execute(
|
|
select(CustomerCredential.customer_id, AWSCredential.name, AWSCredential.account_id)
|
|
.join(AWSCredential, AWSCredential.id == CustomerCredential.credential_id)
|
|
.where(CustomerCredential.customer_id.in_(customer_ids))
|
|
.where(CustomerCredential.is_allowed == 1)
|
|
)
|
|
for customer_id, cred_name, account_id in cred_rows:
|
|
cred_map[customer_id].append(f"{cred_name} ({account_id})")
|
|
|
|
user_map: dict[int, list[str]] = defaultdict(list)
|
|
user_rows = await session.execute(
|
|
select(User.customer_id, User.username).where(User.customer_id.in_(customer_ids))
|
|
)
|
|
for customer_id, username in user_rows:
|
|
user_map[customer_id].append(username)
|
|
|
|
for customer in customers:
|
|
# attach additional presentation fields for API response
|
|
setattr(customer, "credential_names", cred_map.get(customer.id, []))
|
|
setattr(customer, "usernames", user_map.get(customer.id, []))
|
|
|
|
return customers
|
|
|
|
|
|
async def create_customer(session: AsyncSession, data: dict, actor: User) -> Customer:
|
|
customer = Customer(**data)
|
|
session.add(customer)
|
|
await session.commit()
|
|
await session.refresh(customer)
|
|
session.add(
|
|
AuditLog(
|
|
user_id=actor.id,
|
|
customer_id=None,
|
|
action=AuditAction.CUSTOMER_CREATE,
|
|
resource_type=AuditResourceType.CUSTOMER,
|
|
resource_id=customer.id,
|
|
description=f"Create customer {customer.name}",
|
|
)
|
|
)
|
|
await session.commit()
|
|
return customer
|
|
|
|
|
|
async def update_customer(session: AsyncSession, customer_id: int, data: dict, actor: User) -> Customer:
|
|
customer = await session.get(Customer, customer_id)
|
|
if not customer:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Customer not found")
|
|
for field, value in data.items():
|
|
setattr(customer, field, value)
|
|
await session.commit()
|
|
await session.refresh(customer)
|
|
session.add(
|
|
AuditLog(
|
|
user_id=actor.id,
|
|
customer_id=customer.id,
|
|
action=AuditAction.CUSTOMER_UPDATE,
|
|
resource_type=AuditResourceType.CUSTOMER,
|
|
resource_id=customer.id,
|
|
description=f"Update customer {customer.name}",
|
|
payload=data,
|
|
)
|
|
)
|
|
await session.commit()
|
|
return customer
|
|
|
|
|
|
async def delete_customer(session: AsyncSession, customer_id: int, actor: User) -> None:
|
|
customer = await session.get(Customer, customer_id)
|
|
if not customer:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Customer not found")
|
|
await session.delete(customer)
|
|
session.add(
|
|
AuditLog(
|
|
user_id=actor.id,
|
|
customer_id=customer.id,
|
|
action=AuditAction.CUSTOMER_DELETE,
|
|
resource_type=AuditResourceType.CUSTOMER,
|
|
resource_id=customer.id,
|
|
description=f"Delete customer {customer.name}",
|
|
)
|
|
)
|
|
await session.commit()
|