diff --git a/TrackingToolWebAU/api.py b/TrackingToolWebAU/api.py index 893ebe0..c4e0b4c 100644 --- a/TrackingToolWebAU/api.py +++ b/TrackingToolWebAU/api.py @@ -30,6 +30,7 @@ def sync_checkin(email: str, timestamp_ms: int, image_data: bytes, student_name: "image": image_b64, } + print("[sync_checkin] payload:", {k: v for k, v in payload.items() if k != "image"}) try: response = requests.post(HOST + "/api/log-time/check-in-out", json=payload) response.raise_for_status() diff --git a/TrackingToolWebAU/main.py b/TrackingToolWebAU/main.py index 0ba4738..cac3b61 100644 --- a/TrackingToolWebAU/main.py +++ b/TrackingToolWebAU/main.py @@ -259,7 +259,7 @@ async def register_student( @app.post("/checkin") -async def checkin(background_tasks: BackgroundTasks, file: UploadFile = File(...), camera_id: str = Form("cam1"), db: Session = Depends(get_db)): +async def checkin(file: UploadFile = File(...), camera_id: str = Form("cam1"), db: Session = Depends(get_db)): image_data = await file.read() # Phương án 3: resize ảnh trước khi detect — bỏ disk I/O @@ -341,7 +341,28 @@ async def checkin(background_tasks: BackgroundTasks, file: UploadFile = File(... ).fetchone() status = "check out" if last_log and last_log.status == "check in" else "check in" - insert_result = db.execute( + try: + res = sync_checkin( + enc_emails.get(best_student, ""), + int(now.timestamp() * 1000), + image_data, + enc_names.get(best_student, ""), + status, + ) + except Exception as e: + logging.error(f"MS sync error: {e}") + return {"message": "Server sync failed, checkin not recorded.", "status": False} + + if res.get("Status") == "ERROR": + msg = f"[MS Server] {res.get('Msg', 'Unknown error')}" + logging.warning(f"MS rejected checkin: {msg}") + return {"message": msg, "status": False} + + # Ghi log sau khi server xác nhận thành công + check_in_flag = (res.get("data") or {}).get("checkIn") + final_status = ("check in" if check_in_flag else "check out") if check_in_flag is not None else status + + db.execute( text(""" INSERT INTO checkin_logs (student_id, time, camera_id, status) VALUES (:student_id, :time, :camera_id, :status) @@ -350,43 +371,11 @@ async def checkin(background_tasks: BackgroundTasks, file: UploadFile = File(... "student_id": best_student, "time": now, "camera_id": camera_id, - "status": status + "status": final_status } ) - log_id = insert_result.lastrowid db.commit() - def _sync_to_ms(email: str, timestamp_ms: int, img_data: bytes, name: str, local_status: str, checkin_log_id: int): - try: - res = sync_checkin(email, timestamp_ms, img_data, name, local_status) - check_in_flag = res.get("data", {}).get("checkIn") - if check_in_flag is None: - return - ms_status = "check in" if check_in_flag else "check out" - if ms_status != local_status: - fix_db = SessionLocal() - try: - fix_db.execute( - text("UPDATE checkin_logs SET status = :status WHERE id = :id"), - {"status": ms_status, "id": checkin_log_id} - ) - fix_db.commit() - logging.info(f"Corrected log #{checkin_log_id}: {local_status} → {ms_status}") - finally: - fix_db.close() - except Exception as e: - logging.error(f"MS sync error: {e}") - - background_tasks.add_task( - _sync_to_ms, - enc_emails.get(best_student, ""), - int(now.timestamp() * 1000), - image_data, - enc_names.get(best_student, ""), - status, - log_id, - ) - student = db.execute( text(""" SELECT id, name, email @@ -402,7 +391,7 @@ async def checkin(background_tasks: BackgroundTasks, file: UploadFile = File(... "email": student.email, } if student else None - return {"message": f"{status} successful for {enc_names.get(best_student)} (dist={best_distance:.4f})", "status": True, "status_type": status, "data": user_data} + return {"message": f"{final_status} successful for {enc_names.get(best_student)} (dist={best_distance:.4f})", "status": True, "status_type": final_status, "data": user_data} # Nếu không thỏa threshold/rule thì trả no match (và log lý do) reasons = [] @@ -490,7 +479,7 @@ def delete_user(user_id: int, db: Session = Depends(get_db)): {"id": user_id} ).fetchone() if not student: - raise HTTPException(status_code=404, detail="User not found") + raise HTTPException(status_code=404, detail="User not found in local database") db.execute(text("DELETE FROM student_encodings WHERE student_id = :id"), {"id": user_id}) db.execute(text("DELETE FROM checkin_logs WHERE student_id = :id"), {"id": user_id})