초기 커밋 - EV AS 관리 시스템

This commit is contained in:
root
2026-04-18 06:18:58 +09:00
commit 7a5c397983
52 changed files with 6044 additions and 0 deletions

97
backend/routers/costs.py Normal file
View File

@@ -0,0 +1,97 @@
from fastapi import APIRouter, Depends, HTTPException, Form
from sqlalchemy.orm import Session
from sqlalchemy import desc
from typing import Optional
from datetime import datetime
from database import get_db
import models
from auth import require_admin
router = APIRouter(prefix="/api/costs", tags=["costs"])
@router.get("")
def list_costs(
cost_status: Optional[str] = None,
cost_party_type: Optional[str] = None,
db: Session = Depends(get_db), _=Depends(require_admin)
):
q = db.query(models.RepairCost).join(models.Repair)
if cost_status: q = q.filter(models.RepairCost.cost_status == cost_status)
if cost_party_type: q = q.filter(models.RepairCost.cost_party_type == cost_party_type)
q = q.order_by(desc(models.RepairCost.reviewed_at))
result = []
for cost in q.all():
repair = cost.repair
rids = [rr.report_id for rr in repair.report_links]
charger_id, station_name, charger_type = None, None, None
if rids:
r = db.query(models.Report).filter_by(id=rids[0]).first()
if r and r.charger:
charger_id = r.charger_id
station_name = r.charger.station_name
charger_type = r.charger.charger_type.name if r.charger.charger_type else None
result.append({
"id": cost.id, "repair_id": cost.repair_id,
"report_ids": rids, "charger_id": charger_id,
"station_name": station_name, "charger_type": charger_type,
"mechanic_name": repair.mechanic.name if repair.mechanic else None,
"mechanic_company": repair.mechanic.company if repair.mechanic else None,
"completed_at": repair.completed_at.isoformat() if repair.completed_at else None,
"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,
"reviewed_by_name": cost.reviewer.name if cost.reviewer else None,
"reviewed_at": cost.reviewed_at.isoformat() if cost.reviewed_at else None,
})
return result
@router.get("/stats")
def cost_stats(db: Session = Depends(get_db), _=Depends(require_admin)):
from sqlalchemy import func, extract
now = datetime.now()
monthly = db.query(func.sum(models.RepairCost.cost_amount)).filter(
extract('year', models.RepairCost.reviewed_at) == now.year,
extract('month', models.RepairCost.reviewed_at) == now.month,
).scalar() or 0
pending = db.query(models.RepairCost).filter_by(cost_status="pending").count()
return {"monthly_total": monthly, "pending_count": pending}
@router.post("/repair/{repair_id}")
def upsert_cost(
repair_id: int,
root_cause: str = Form(""),
admin_note: str = Form(""),
cost_party_type: str = Form(...),
cost_party_manufacturer_id: Optional[int] = Form(None),
cost_party_custom: str = Form(""),
cost_amount: int = Form(0),
cost_status: str = Form("pending"),
db: Session = Depends(get_db),
current_user: models.User = Depends(require_admin)
):
repair = db.query(models.Repair).filter_by(id=repair_id).first()
if not repair: raise HTTPException(404, "조치 내역을 찾을 수 없습니다.")
cost = db.query(models.RepairCost).filter_by(repair_id=repair_id).first()
if cost:
cost.root_cause = root_cause; cost.admin_note = admin_note
cost.cost_party_type = cost_party_type
cost.cost_party_manufacturer_id = cost_party_manufacturer_id or None
cost.cost_party_custom = cost_party_custom or None
cost.cost_amount = cost_amount; cost.cost_status = cost_status
cost.reviewed_by = current_user.id; cost.reviewed_at = datetime.now()
else:
cost = models.RepairCost(
repair_id=repair_id, root_cause=root_cause, admin_note=admin_note,
cost_party_type=cost_party_type,
cost_party_manufacturer_id=cost_party_manufacturer_id or None,
cost_party_custom=cost_party_custom or None,
cost_amount=cost_amount, cost_status=cost_status,
reviewed_by=current_user.id, reviewed_at=datetime.now()
)
db.add(cost)
db.commit()
return {"ok": True}