Files
ev-charger-as/backend/routers/reports.py.bak
2026-04-18 06:18:58 +09:00

137 lines
5.7 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from sqlalchemy.orm import Session
from sqlalchemy import desc
from typing import List, Optional
from datetime import datetime
from database import get_db
import models
from auth import require_admin, get_current_user
from utils import save_upload
router = APIRouter(prefix="/api/reports", tags=["reports"])
def _fmt_report(r: models.Report, db: Session):
c = r.charger
repair_id = None
if r.repair_links:
repair_id = r.repair_links[0].repair_id
return {
"id": r.id, "charger_id": r.charger_id,
"charger_name": c.name if c else None,
"station_name": c.station_name if c else None,
"cpo_name": c.cpo_name if c else None,
"charger_type": c.charger_type.name if c and c.charger_type else None,
"installed_at": str(c.installed_at) if c and c.installed_at else None,
"issue_types": r.issue_types, "issue_detail": r.issue_detail,
"error_code": r.error_code, "contact": r.contact,
"occurred_at": r.occurred_at.isoformat() if r.occurred_at else None,
"reported_at": r.reported_at.isoformat() if r.reported_at else None,
"gps_lat": r.gps_lat, "gps_lng": r.gps_lng,
"status": r.status,
"photos": [p.file_path for p in r.photos],
"repair_id": repair_id,
}
@router.post("")
async def create_report(
charger_id: str = Form(...),
issue_types: str = Form(...), # JSON 배열 문자열
issue_detail: str = Form(""),
error_code: str = Form(""),
occurred_at: Optional[str] = Form(None),
contact: str = Form(""),
consent: bool = Form(False),
gps_lat: Optional[float] = Form(None),
gps_lng: Optional[float] = Form(None),
photos: List[UploadFile] = File(default=[]),
db: Session = Depends(get_db)
):
import json
charger = db.query(models.Charger).filter_by(id=charger_id).first()
if not charger: raise HTTPException(404, "충전기를 찾을 수 없습니다.")
# 신고 공개 정책 확인
setting = db.query(models.SystemSetting).filter_by(key="report_visibility_policy").first()
policy = setting.value if setting else "immediate"
initial_status = "pending_approval" if policy == "admin_approval" else "pending"
issue_list = json.loads(issue_types) if isinstance(issue_types, str) else issue_types
r = models.Report(
charger_id=charger_id, issue_types=issue_list,
issue_detail=issue_detail or None, error_code=error_code or None,
occurred_at=datetime.fromisoformat(occurred_at) if occurred_at else None,
contact=contact or None, consent=consent,
gps_lat=gps_lat, gps_lng=gps_lng, status=initial_status
)
db.add(r); db.commit(); db.refresh(r)
for photo in photos:
if photo.filename:
path = save_upload(photo, f"reports/{r.id}")
db.add(models.ReportPhoto(report_id=r.id, file_path=path))
db.commit()
return {"id": r.id, "status": r.status}
@router.get("")
def list_reports(
status: Optional[str] = None,
charger_id: Optional[str] = None,
db: Session = Depends(get_db),
current_user: models.User = Depends(get_current_user)
):
q = db.query(models.Report).order_by(desc(models.Report.reported_at))
if status: q = q.filter(models.Report.status == status)
if charger_id: q = q.filter(models.Report.charger_id == charger_id)
# 정비사는 공개된 것만 (승인 대기 제외)
if current_user.role == "mechanic":
q = q.filter(models.Report.status != "pending_approval")
return [_fmt_report(r, db) for r in q.all()]
@router.get("/{report_id}")
def get_report(report_id: int, db: Session = Depends(get_db),
current_user: models.User = Depends(get_current_user)):
r = db.query(models.Report).filter_by(id=report_id).first()
if not r: raise HTTPException(404)
result = _fmt_report(r, db)
# 수리 정보 포함
if r.repair_links:
repair = r.repair_links[0].repair
cost = repair.cost
result["repair"] = {
"id": repair.id,
"mechanic_name": repair.mechanic.name if repair.mechanic else None,
"mechanic_company": repair.mechanic.company if repair.mechanic else None,
"repair_types": repair.repair_types,
"description": repair.description,
"started_at": repair.started_at.isoformat(),
"completed_at": repair.completed_at.isoformat() if repair.completed_at else None,
"result_status": repair.result_status,
"photos_before": [p.file_path for p in repair.photos if p.photo_type == "before"],
"photos_after": [p.file_path for p in repair.photos if p.photo_type == "after"],
"cost": {
"root_cause": cost.root_cause,
"admin_note": cost.admin_note,
"cost_party_type": cost.cost_party_type,
"cost_party_custom": cost.cost_party_custom,
"cost_amount": cost.cost_amount,
"cost_status": cost.cost_status,
"manufacturer_name": cost.manufacturer.name if cost.manufacturer else None,
} if cost else None
}
return result
@router.patch("/{report_id}/approve")
def approve_report(report_id: int, db: Session = Depends(get_db), _=Depends(require_admin)):
r = db.query(models.Report).filter_by(id=report_id).first()
if not r: raise HTTPException(404)
r.status = "pending"; db.commit()
return {"ok": True}
@router.patch("/{report_id}/status")
def update_status(report_id: int, status: str = Form(...),
db: Session = Depends(get_db), _=Depends(require_admin)):
r = db.query(models.Report).filter_by(id=report_id).first()
if not r: raise HTTPException(404)
r.status = status; db.commit()
return {"ok": True}