""" CIQ Verification App Streamlit interface to verify CIQ parameters against dump database. Supports 2G, 3G, and LTE verification with optional file uploads. """ import pandas as pd import streamlit as st from queries.verify_ciq import ( generate_verification_report, process_dump_gsm, process_dump_lte, process_dump_wcdma, read_ciq_file, verify_2g, verify_3g, verify_lte, ) st.title("🔍 CIQ Verification") st.markdown( """ Vérifiez que les paramètres CIQ correspondent aux valeurs du dump OML. - **Dump** : Obligatoire (format .xlsb) - **CIQ** : Au moins un fichier CIQ (2G, 3G ou LTE) est requis """ ) # File uploaders st.subheader("📁 Fichiers d'entrée") dump_file = st.file_uploader( "Upload Dump (xlsb)", type=["xlsb"], key="verify_dump", help="Fichier dump obligatoire" ) col1, col2, col3 = st.columns(3) with col1: ciq_2g_file = st.file_uploader( "CIQ 2G (optionnel)", type=["xlsx", "xls"], key="verify_ciq_2g" ) with col2: ciq_3g_file = st.file_uploader( "CIQ 3G (optionnel)", type=["xlsx", "xls"], key="verify_ciq_3g" ) with col3: ciq_lte_file = st.file_uploader( "CIQ LTE (optionnel)", type=["xlsx", "xls"], key="verify_ciq_lte" ) # Validation if dump_file is None: st.info("⬆️ Veuillez uploader le fichier dump (xlsb).") st.stop() if ciq_2g_file is None and ciq_3g_file is None and ciq_lte_file is None: st.warning("⚠️ Au moins un fichier CIQ (2G, 3G ou LTE) est requis.") st.stop() # Verify button if st.button("🔎 Vérifier", type="primary"): try: results_2g = None results_3g = None results_lte = None with st.spinner("Traitement en cours..."): # Process 2G if provided if ciq_2g_file is not None: st.text("📶 Traitement 2G...") dump_gsm = process_dump_gsm(dump_file) dump_file.seek(0) # Reset file pointer ciq_2g_df = read_ciq_file(ciq_2g_file) results_2g = verify_2g(ciq_2g_df, dump_gsm) # Process 3G if provided if ciq_3g_file is not None: st.text("📶 Traitement 3G...") dump_wcdma = process_dump_wcdma(dump_file) dump_file.seek(0) # Reset file pointer ciq_3g_df = read_ciq_file(ciq_3g_file) results_3g = verify_3g(ciq_3g_df, dump_wcdma) # Process LTE if provided if ciq_lte_file is not None: st.text("📶 Traitement LTE...") dump_lte = process_dump_lte(dump_file) dump_file.seek(0) # Reset file pointer ciq_lte_df = read_ciq_file(ciq_lte_file) results_lte = verify_lte(ciq_lte_df, dump_lte) # Generate report sheets, excel_bytes = generate_verification_report( results_2g=results_2g, results_3g=results_3g, results_lte=results_lte, ) st.session_state["verify_results_2g"] = results_2g st.session_state["verify_results_3g"] = results_3g st.session_state["verify_results_lte"] = results_lte st.session_state["verify_sheets"] = sheets st.session_state["verify_excel_bytes"] = excel_bytes st.success("✅ Vérification terminée!") except Exception as e: st.error(f"❌ Erreur: {e}") import traceback st.code(traceback.format_exc()) # Display results results_2g = st.session_state.get("verify_results_2g") results_3g = st.session_state.get("verify_results_3g") results_lte = st.session_state.get("verify_results_lte") sheets = st.session_state.get("verify_sheets") excel_bytes = st.session_state.get("verify_excel_bytes") def display_stats(stats: dict, tech: str): """Display verification statistics.""" col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Total Cells", stats["total_cells"]) with col2: st.metric("✅ OK", stats["ok_count"]) with col3: st.metric("⚠️ Mismatch", stats["mismatch_count"]) with col4: st.metric("❓ Not Found", stats["not_found_count"]) def style_results(df: pd.DataFrame) -> pd.DataFrame: """Apply styling to highlight mismatches.""" def highlight_status(val): if val == "OK": return "background-color: #d4edda; color: #155724;" elif val == "MISMATCH": return "background-color: #f8d7da; color: #721c24;" elif val == "NOT_FOUND": return "background-color: #fff3cd; color: #856404;" return "" def highlight_match(val): if val is True: return "background-color: #d4edda;" elif val is False: return "background-color: #f8d7da;" return "" # Get status column name status_col = "Status" # Apply styling (using map instead of deprecated applymap) styled = df.style.map( highlight_status, subset=[status_col] ) # Highlight match columns match_cols = [c for c in df.columns if c.endswith("_Match")] if match_cols: styled = styled.map(highlight_match, subset=match_cols) return styled if sheets: st.divider() st.subheader("📊 Résultats de la vérification") tabs = [] tab_names = [] if results_2g: tab_names.append("2G") if results_3g: tab_names.append("3G") if results_lte: tab_names.append("LTE") if tab_names: tabs = st.tabs(tab_names) tab_idx = 0 if results_2g: with tabs[tab_idx]: st.markdown("### 📶 Vérification 2G") display_stats(results_2g[1], "2G") st.dataframe( style_results(results_2g[0]), use_container_width=True, hide_index=True, ) tab_idx += 1 if results_3g: with tabs[tab_idx]: st.markdown("### 📶 Vérification 3G") display_stats(results_3g[1], "3G") st.dataframe( style_results(results_3g[0]), use_container_width=True, hide_index=True, ) tab_idx += 1 if results_lte: with tabs[tab_idx]: st.markdown("### 📶 Vérification LTE") display_stats(results_lte[1], "LTE") st.dataframe( style_results(results_lte[0]), use_container_width=True, hide_index=True, ) if excel_bytes: st.divider() st.download_button( label="📥 Télécharger le rapport de vérification (Excel)", data=excel_bytes, file_name="CIQ_Verification_Report.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type="primary", )