import gradio as gr from src.services.auth_service import is_admin from src.services.closing_service import close_day, compute_default_business_date_to_close from src.db.connection import get_conn from src.db.closing import recent_closings def render_closing_tab(db_path: str, auth_state: gr.State): with gr.Column() as panel: gr.Markdown("## Daily Closing (06:00 Asia/Muscat)") business_date = gr.Textbox(label="Business date to close (YYYY-MM-DD)", value=compute_default_business_date_to_close()) note = gr.Textbox(label="Mandatory note", lines=2, value="Daily closing") close_btn = gr.Button("Close Day Now (Admin only)", variant="primary") msg = gr.Markdown("") pdf_file = gr.File(label="Generated PDF (download)", interactive=False) gr.Markdown("### Recent closings") closings_table = gr.Dataframe( headers=["business_date","closed_at_utc","closed_by","note","pdf_path"], interactive=False, row_count=10, col_count=5, ) refresh = gr.Button("Refresh Closings") def _refresh(auth): if not auth: return [] conn = get_conn(db_path) try: rows = recent_closings(conn, limit=14) finally: conn.close() return [[r["business_date"], r["closed_at_utc"], r["closed_by"], r["note"], r["pdf_path"]] for r in rows] def _close(bd, note_text, auth): if not auth: return "❌ Please login.", None if not is_admin(auth): return "❌ Admin only (login as Dr).", None if not bd or not bd.strip(): return "❌ Business date required.", None if not note_text or not note_text.strip(): return "❌ Note required.", None pdf_bytes, pdf_path = close_day(db_path, bd.strip(), auth["username"], note_text.strip()) # Gradio File expects a file path, easiest is to return pdf_path return f"✅ Closed **{bd.strip()}**. PDF saved at `{pdf_path}`", pdf_path refresh.click(_refresh, inputs=[auth_state], outputs=[closings_table]) panel.load(_refresh, inputs=[auth_state], outputs=[closings_table]) close_btn.click(_close, inputs=[business_date, note, auth_state], outputs=[msg, pdf_file]).then( _refresh, inputs=[auth_state], outputs=[closings_table] ) return panel, {}