## 처리시간 지표 - 업무시간 기준(09-18 평일) / 공휴일 제외 24h / 달력 기준 3가지 모드 선택 - 공휴일 DB 관리 (holidays 테이블, 수동 등록·삭제·일괄 추가) - 2026년 공휴일 등록 지원 - 설정 페이지에서 라디오 버튼으로 모드 선택 ## 대시보드 차트 - 월별 평균 처리시간 막대 차트 추가 - 월별 신고 접수 건수 누적 막대 차트 추가 - 월별 → 일별 드릴다운 (막대 클릭 시 해당 월의 일별 차트로 전환) - 일별 막대 클릭 시 처리 완료/신고 접수 상세 내역 모달 - 충전기별 누적 고장 건수 Top 10 수평 막대 차트 추가 ## 신고 목록 - # 컬럼을 DB PK 대신 현재 목록 순서(1, 2, 3…)로 표시 - 엑셀 export 접수번호도 순차번호로 변경 ## 모바일 네비게이션 버그 수정 - 모바일에서 가로 오버플로우 시 nav가 body 넓이로 늘어나 햄버거 버튼이 화면 밖으로 밀리는 문제 수정 - nav를 position:fixed + body padding-top:54px 로 변경 (전체 페이지 적용) - 충전기 관리·신고 목록 페이지 지도 컨테이너에 isolation:isolate 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Form
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
from database import get_db
|
|
import models
|
|
from auth import verify_password, create_access_token, get_current_user, hash_password
|
|
|
|
router = APIRouter(prefix="/api/auth", tags=["auth"])
|
|
|
|
@router.post("/login")
|
|
def login(form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
|
|
user = db.query(models.User).filter(
|
|
models.User.username == form.username
|
|
).first()
|
|
if not user or not verify_password(form.password, user.password_hash):
|
|
raise HTTPException(status_code=401, detail="아이디 또는 비밀번호가 올바르지 않습니다.")
|
|
if getattr(user, 'is_pending', False):
|
|
raise HTTPException(status_code=403, detail="가입 승인 대기 중입니다. 관리자 승인 후 이용 가능합니다.")
|
|
if not user.is_active:
|
|
raise HTTPException(status_code=403, detail="비활성화된 계정입니다. 관리자에게 문의하세요.")
|
|
token = create_access_token({"sub": str(user.id)})
|
|
return {
|
|
"access_token": token,
|
|
"token_type": "bearer",
|
|
"role": user.role,
|
|
"name": user.name,
|
|
"user_id": user.id
|
|
}
|
|
|
|
@router.post("/register")
|
|
def register(
|
|
username: str = Form(...),
|
|
password: str = Form(...),
|
|
name: str = Form(...),
|
|
phone: str = Form(""),
|
|
company: str = Form(""),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
if db.query(models.User).filter_by(username=username).first():
|
|
raise HTTPException(400, "이미 사용 중인 아이디입니다.")
|
|
user = models.User(
|
|
username=username,
|
|
password_hash=hash_password(password),
|
|
role="mechanic",
|
|
name=name,
|
|
phone=phone or None,
|
|
company=company or None,
|
|
is_active=False,
|
|
is_pending=True,
|
|
)
|
|
db.add(user); db.commit()
|
|
return {"ok": True}
|
|
|
|
@router.get("/me")
|
|
def me(current_user: models.User = Depends(get_current_user)):
|
|
return {
|
|
"id": current_user.id,
|
|
"username": current_user.username,
|
|
"role": current_user.role,
|
|
"name": current_user.name,
|
|
"company": current_user.company,
|
|
}
|