181 lines
7.1 KiB
Python
181 lines
7.1 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from starlette.requests import Request
|
|
|
|
from app.core.rbac import require_any_permission, require_permission
|
|
from app.db.database import get_db
|
|
from app.models.repair import Repair
|
|
from app.models.repair_estimate import RepairEstimate
|
|
from app.models.user import User
|
|
from app.repositories.repair_estimate_repository import RepairEstimateRepository
|
|
from app.repositories.repair_repository import RepairRepository
|
|
from app.schemas.repair_estimate import (
|
|
PublicEstimateDecisionRequest,
|
|
PublicEstimateResponse,
|
|
RepairEstimateCreate,
|
|
RepairEstimateEventResponse,
|
|
RepairEstimateResponse,
|
|
RepairEstimateUpdate,
|
|
)
|
|
from app.services.repair_estimate_service import RepairEstimateService
|
|
from app.services.repair_public_link_service import RepairPublicLinkService
|
|
|
|
router = APIRouter(tags=["Repair Estimates"])
|
|
|
|
|
|
def get_repair_or_404(db: Session, repair_id: int) -> Repair:
|
|
repair = RepairRepository.get_by_id(db, repair_id)
|
|
if repair is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Reparatur nicht gefunden")
|
|
return repair
|
|
|
|
|
|
def get_estimate_or_404(db: Session, repair_id: int, estimate_id: int) -> RepairEstimate:
|
|
estimate = RepairEstimateRepository.get(db, repair_id=repair_id, estimate_id=estimate_id)
|
|
if estimate is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Kostenvoranschlag nicht gefunden")
|
|
return estimate
|
|
|
|
|
|
@router.get("/repairs/{repair_id}/estimates", response_model=list[RepairEstimateResponse])
|
|
def list_estimates(
|
|
repair_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.read")),
|
|
):
|
|
get_repair_or_404(db, repair_id)
|
|
return RepairEstimateRepository.list_by_repair(db, repair_id)
|
|
|
|
|
|
@router.post("/repairs/{repair_id}/estimates", response_model=RepairEstimateResponse, status_code=status.HTTP_201_CREATED)
|
|
def create_estimate(
|
|
repair_id: int,
|
|
payload: RepairEstimateCreate,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.create")),
|
|
):
|
|
repair = get_repair_or_404(db, repair_id)
|
|
return RepairEstimateService.create(db, repair, payload, actor=current_user, request=request)
|
|
|
|
|
|
@router.get("/repairs/{repair_id}/estimates/{estimate_id}", response_model=RepairEstimateResponse)
|
|
def get_estimate(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.read")),
|
|
):
|
|
get_repair_or_404(db, repair_id)
|
|
return get_estimate_or_404(db, repair_id, estimate_id)
|
|
|
|
|
|
@router.put("/repairs/{repair_id}/estimates/{estimate_id}", response_model=RepairEstimateResponse)
|
|
def update_estimate(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
payload: RepairEstimateUpdate,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.update")),
|
|
):
|
|
repair = get_repair_or_404(db, repair_id)
|
|
estimate = get_estimate_or_404(db, repair_id, estimate_id)
|
|
return RepairEstimateService.update(db, repair, estimate, payload, actor=current_user, request=request)
|
|
|
|
|
|
@router.delete("/repairs/{repair_id}/estimates/{estimate_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
def delete_estimate(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.delete")),
|
|
):
|
|
repair = get_repair_or_404(db, repair_id)
|
|
estimate = get_estimate_or_404(db, repair_id, estimate_id)
|
|
RepairEstimateService.delete(db, repair, estimate, actor=current_user, request=request)
|
|
return None
|
|
|
|
|
|
@router.post("/repairs/{repair_id}/estimates/{estimate_id}/send", response_model=RepairEstimateResponse)
|
|
def send_estimate(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.send")),
|
|
):
|
|
repair = get_repair_or_404(db, repair_id)
|
|
estimate = get_estimate_or_404(db, repair_id, estimate_id)
|
|
return RepairEstimateService.send(db, repair, estimate, actor=current_user, request=request)
|
|
|
|
|
|
@router.post("/repairs/{repair_id}/estimates/{estimate_id}/cancel", response_model=RepairEstimateResponse)
|
|
def cancel_estimate(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_any_permission(["repair_estimates.update", "repair_estimates.send"])),
|
|
):
|
|
repair = get_repair_or_404(db, repair_id)
|
|
estimate = get_estimate_or_404(db, repair_id, estimate_id)
|
|
return RepairEstimateService.cancel(db, repair, estimate, actor=current_user, request=request)
|
|
|
|
|
|
@router.get("/repairs/{repair_id}/estimates/{estimate_id}/events", response_model=list[RepairEstimateEventResponse])
|
|
def list_estimate_events(
|
|
repair_id: int,
|
|
estimate_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_permission("repair_estimates.read")),
|
|
):
|
|
estimate = get_estimate_or_404(db, repair_id, estimate_id)
|
|
return estimate.events
|
|
|
|
|
|
def get_public_repair_and_estimate(db: Session, token: str) -> tuple[Repair, RepairEstimate]:
|
|
public_link = RepairPublicLinkService.get_public_link_or_404(db, token)
|
|
repair = public_link.repair
|
|
estimate = RepairEstimateRepository.get_latest_public(db, repair.id)
|
|
if estimate is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Kostenvoranschlag nicht gefunden")
|
|
RepairRepository.mark_public_link_used(db, public_link)
|
|
return repair, estimate
|
|
|
|
|
|
@router.post("/public/repairs/status/{token}/estimate/approve", response_model=PublicEstimateResponse)
|
|
def approve_public_estimate(
|
|
token: str,
|
|
payload: PublicEstimateDecisionRequest,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
repair, estimate = get_public_repair_and_estimate(db, token)
|
|
updated = RepairEstimateService.customer_decision(db, repair, estimate, "approve", payload, request=request)
|
|
return RepairEstimateService.public_response(updated)
|
|
|
|
|
|
@router.post("/public/repairs/status/{token}/estimate/decline", response_model=PublicEstimateResponse)
|
|
def decline_public_estimate(
|
|
token: str,
|
|
payload: PublicEstimateDecisionRequest,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
repair, estimate = get_public_repair_and_estimate(db, token)
|
|
updated = RepairEstimateService.customer_decision(db, repair, estimate, "decline", payload, request=request)
|
|
return RepairEstimateService.public_response(updated)
|
|
|
|
|
|
@router.post("/public/repairs/status/{token}/estimate/question", response_model=PublicEstimateResponse)
|
|
def question_public_estimate(
|
|
token: str,
|
|
payload: PublicEstimateDecisionRequest,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
repair, estimate = get_public_repair_and_estimate(db, token)
|
|
updated = RepairEstimateService.customer_decision(db, repair, estimate, "question", payload, request=request)
|
|
return RepairEstimateService.public_response(updated)
|