Merge pull request 'update(server): connect api to erp and add func remove user' (#163) from zelda.checkin-for-au into master
Reviewed-on: #163
This commit is contained in:
commit
95e4e833b5
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
Loading…
Reference in New Issue