From d429ed627d8ad9c4fb6e032b15db3038e879750f Mon Sep 17 00:00:00 2001 From: byun Date: Mon, 1 Jun 2026 15:30:33 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=E2=80=94=20=EC=A1=B0=EC=B9=98=20=EC=8B=9C=EC=9E=91/=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=EA=B0=81=20=EC=A7=81=EC=A0=91=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 정비사가 조치 입력 시 시작·완료 시각을 직접 수정할 수 있도록 변경. 현장 처리 후 나중에 입력하는 경우 실제 조치 시간을 정확히 기록 가능. - repair.html: 자동기록 안내문구 → datetime-local 입력 필드 2개로 교체 (페이지 로드 시 현재 시각 기본 설정, 편집 모드에서 기존 값 복원) - repairs.py: POST/PUT 엔드포인트에 started_at_input / completed_at_input Form 파라미터 추가, 미입력 시 datetime.now() 유지 Co-Authored-By: Claude Sonnet 4.6 --- backend/routers/repairs.py | 20 ++++++++++++++--- frontend/static/pages/mechanic/repair.html | 26 +++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/backend/routers/repairs.py b/backend/routers/repairs.py index e1270df..e41be62 100644 --- a/backend/routers/repairs.py +++ b/backend/routers/repairs.py @@ -125,12 +125,21 @@ def get_repair(repair_id: int, db: Session = Depends(get_db), return _fmt_repair(repair) +def _parse_dt(s: Optional[str]) -> Optional[datetime]: + if not s: return None + try: + return datetime.fromisoformat(s) + except Exception: + return None + @router.post("") async def create_repair( report_ids: str = Form(...), repair_types: str = Form(...), description: str = Form(...), result_status: str = Form("done"), + started_at_input: Optional[str] = Form(None), + completed_at_input: Optional[str] = Form(None), mechanic_lat: Optional[float] = Form(None), mechanic_lng: Optional[float] = Form(None), photos_before: List[UploadFile] = File(default=[]), @@ -138,13 +147,14 @@ async def create_repair( db: Session = Depends(get_db), current_user: models.User = Depends(require_mechanic) ): + now = datetime.now() rids = json.loads(report_ids) repair = models.Repair( mechanic_id=current_user.id, repair_types=json.loads(repair_types), description=description, - started_at=datetime.now(), - completed_at=datetime.now(), + started_at=_parse_dt(started_at_input) or now, + completed_at=_parse_dt(completed_at_input) or now, result_status=result_status, mechanic_lat=mechanic_lat, mechanic_lng=mechanic_lng, @@ -175,6 +185,8 @@ async def update_repair( repair_types: str = Form(...), description: str = Form(...), result_status: str = Form("done"), + started_at_input: Optional[str] = Form(None), + completed_at_input: Optional[str] = Form(None), mechanic_lat: Optional[float] = Form(None), mechanic_lng: Optional[float] = Form(None), photos_before: List[UploadFile] = File(default=[]), @@ -192,7 +204,9 @@ async def update_repair( repair.repair_types = json.loads(repair_types) repair.description = description repair.result_status = result_status - repair.completed_at = datetime.now() + if started_at_input: + repair.started_at = _parse_dt(started_at_input) or repair.started_at + repair.completed_at = _parse_dt(completed_at_input) or datetime.now() if mechanic_lat is not None: repair.mechanic_lat = mechanic_lat if mechanic_lng is not None: repair.mechanic_lng = mechanic_lng diff --git a/frontend/static/pages/mechanic/repair.html b/frontend/static/pages/mechanic/repair.html index 65d6bd5..78e7dab 100644 --- a/frontend/static/pages/mechanic/repair.html +++ b/frontend/static/pages/mechanic/repair.html @@ -81,8 +81,15 @@ -
- 🕐 조치 시작 시간: (자동 기록) +
+
+ + +
+
+ + +
@@ -139,8 +146,15 @@ const chargerId = params.get('charger_id'); // 신규 모드 const initReportId = params.get('report_id'); const isEditMode = !!repairId; +// datetime-local 입력값 포맷: "YYYY-MM-DDTHH:mm" +function toLocalDtInput(date) { + const d = new Date(date); + const pad = n => String(n).padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; +} const startTime = new Date(); -document.getElementById('startedAt').textContent = startTime.toLocaleString('ko-KR'); +document.getElementById('startedAt').value = toLocalDtInput(startTime); +document.getElementById('completedAt').value = toLocalDtInput(startTime); const selectedReports = new Set(); if (initReportId) selectedReports.add(parseInt(initReportId)); @@ -222,6 +236,8 @@ async function loadEdit() { // 폼 미리채우기 — 조치유형 동적 로드 후 체크 복원 await loadRepairTypes(repair.repair_types || []); document.getElementById('description').value = repair.description || ''; + if (repair.started_at) document.getElementById('startedAt').value = toLocalDtInput(repair.started_at); + if (repair.completed_at) document.getElementById('completedAt').value = toLocalDtInput(repair.completed_at); const sel = document.getElementById('resultStatus'); if (repair.result_status && sel.querySelector(`option[value="${repair.result_status}"]`)) sel.value = repair.result_status; @@ -318,6 +334,10 @@ async function submitForm(isDone) { fd.append('repair_types', JSON.stringify(types)); fd.append('description', desc); fd.append('result_status', resultStatus); + const startedAtVal = document.getElementById('startedAt').value; + const completedAtVal = document.getElementById('completedAt').value; + if (startedAtVal) fd.append('started_at_input', startedAtVal); + if (completedAtVal) fd.append('completed_at_input', completedAtVal); if (lat) fd.append('mechanic_lat', lat); if (lng) fd.append('mechanic_lng', lng); Array.from(document.getElementById('photosBefore').files).forEach(f => fd.append('photos_before', f));