Spaces:
Sleeping
Sleeping
import xml.etree.ElementTree as ET | |
import pandas as pd | |
import json | |
import gradio as gr | |
def get_clients_from_xml(xml_file): | |
"""Extract all clients from XML file and return a list of tuples (id, name)""" | |
try: | |
tree = ET.parse(xml_file.name) | |
root = tree.getroot() | |
clients = [] | |
for client in root.findall(".//client"): | |
client_id = client.get("id") | |
nom = client.get("nom") if client.get("nom") is not None else "" | |
prenom = client.get("prenom") if client.get("prenom") is not None else "" | |
clients.append((client_id, f"{prenom} {nom} (ID: {client_id})")) | |
return clients | |
except Exception as e: | |
print(e) | |
return [] | |
def client_to_json(xml_file, client_id): | |
tree = ET.parse(xml_file) | |
root = tree.getroot() | |
# Find the specific client | |
client = root.find(f".//client[@id='{client_id}']") | |
if client is None: | |
return json.dumps({"error": f"Client ID {client_id} not found"}) | |
def element_to_dict(element): | |
result = {} | |
# Add attributes | |
if element.attrib: | |
result.update(element.attrib) | |
# Add text content if it exists and isn't empty | |
if element.text and element.text.strip(): | |
result["_text"] = element.text.strip() | |
# Process child elements | |
for child in element: | |
child_data = element_to_dict(child) | |
if child.tag in result: | |
# If the key already exists, convert it to a list if it isn't already | |
if not isinstance(result[child.tag], list): | |
result[child.tag] = [result[child.tag]] | |
result[child.tag].append(child_data) | |
else: | |
result[child.tag] = child_data | |
return result | |
# Convert client data to dictionary | |
client_data = element_to_dict(client) | |
# Convert to JSON with pretty printing | |
return json.dumps(client_data, indent=2, ensure_ascii=False) | |
def display_nested_json(json_data): | |
# If input is a string, parse it to dict | |
if isinstance(json_data, str): | |
data = json.loads(json_data) | |
else: | |
data = json_data | |
# 1. Basic Client Information | |
basic_info = pd.DataFrame( | |
[ | |
{ | |
"ID": data.get("id"), | |
"Nom": data.get("nom"), | |
"Prénom": data.get("prenom"), | |
"Civilité": data.get("civilite"), | |
"Date Creation": data.get("date_creation"), | |
} | |
] | |
) | |
# 2. Accounts Table | |
accounts_df = extract_accounts(data) | |
# 3. Contact Information | |
contacts_df = extract_contacts(data) | |
# 4. Real Estate (Immobilier) Information | |
immobilier_df = extract_immobilier(data) | |
# 5. Patrimoine Information | |
patrimoine_df = extract_patrimoine(data) | |
# 6. Budget Information | |
budget_df = extract_budget(data) | |
return { | |
"basic_info": basic_info, | |
"accounts": accounts_df, | |
"contacts": contacts_df, | |
"immobilier": immobilier_df, | |
"patrimoine": patrimoine_df, | |
"budget": budget_df, | |
} | |
def extract_accounts(data): | |
if "comptes" in data and "compte" in data["comptes"]: | |
accounts = data["comptes"]["compte"] | |
if isinstance(accounts, dict): | |
accounts = [accounts] | |
accounts_data = [] | |
for account in accounts: | |
situations = account.get("situations", {}) | |
situation_data = situations.get("situation", []) | |
if isinstance(situation_data, dict): | |
situation_data = [situation_data] | |
for situation in situation_data: | |
row = { | |
"Account ID": account.get("id"), | |
"Account Name": account.get("intitule"), | |
"Opening Date": account.get("date_ouverture"), | |
"Valuation Date": situations.get("date_valorisation"), | |
"Valuation Type": situations.get("type_valorisation"), | |
"Support ID": situation.get("support_id"), | |
"Quantity": situation.get("quantite"), | |
"Price": situation.get("cours"), | |
"Value (EUR)": situation.get("valeur_euro"), | |
"Weight (%)": situation.get("poids_ligne"), | |
"PMV (EUR)": situation.get("pmv_euro"), | |
"PMV (%)": situation.get("pmv_pourcentage"), | |
} | |
accounts_data.append(row) | |
accounts_df = pd.DataFrame(accounts_data) | |
numeric_columns = [ | |
"Quantity", | |
"Price", | |
"Value (EUR)", | |
"Weight (%)", | |
"PMV (EUR)", | |
"PMV (%)", | |
] | |
for col in numeric_columns: | |
if col in accounts_df.columns: | |
try: | |
accounts_df[col] = pd.to_numeric(accounts_df[col]) | |
except ValueError: | |
print(f"Warning: Could not convert column {col} to numeric.") | |
else: | |
accounts_df = pd.DataFrame() | |
return accounts_df | |
def extract_contacts(data): | |
if "modes_contacts" in data: | |
contacts = data["modes_contacts"] | |
contacts_df = pd.DataFrame( | |
[ | |
{ | |
"Email": contacts.get("email_personnel"), | |
"Mobile": contacts.get("telephone_mobile"), | |
} | |
] | |
) | |
else: | |
contacts_df = pd.DataFrame() | |
return contacts_df | |
def extract_immobilier(data): | |
if "immobiliers" in data and "immobilier" in data["immobiliers"]: | |
immobilier = data["immobiliers"]["immobilier"] | |
if isinstance(immobilier, dict): | |
immobilier = [immobilier] | |
immobilier_data = [] | |
for item in immobilier: | |
row = { | |
"ID": item.get("id"), | |
"Designation": item.get("designation"), | |
"Address": item.get("adresse", {}).get("adresse"), | |
"City": item.get("adresse", {}).get("ville"), | |
"Postal Code": item.get("adresse", {}).get("code_postal"), | |
"Country": item.get("adresse", {}).get("pays"), | |
"Value": item.get("valeur", {}).get("totale"), | |
"Revenues": item.get("revenus", {}).get("montant"), | |
"Charges": item.get("charges", {}).get("montant"), | |
} | |
immobilier_data.append(row) | |
immobilier_df = pd.DataFrame(immobilier_data) | |
else: | |
immobilier_df = pd.DataFrame() | |
return immobilier_df | |
def extract_patrimoine(data): | |
patrimoine_data = {"actifs": pd.DataFrame(), "passifs": pd.DataFrame()} | |
if "patrimoine" in data: | |
# Extract Actifs | |
if "actifs" in data["patrimoine"]: | |
actifs_items = data["patrimoine"]["actifs"].get("actif", []) | |
if isinstance(actifs_items, dict): | |
actifs_items = [actifs_items] | |
if actifs_items: | |
actifs_data = [] | |
for item in actifs_items: | |
row = { | |
"UUID": item.get("uuid"), | |
"Libellé": item.get("libelle"), | |
"Patrimoine ID": item.get("patrimoine_id"), | |
"Montant (EUR)": item.get("montant_euro"), | |
"Système": item.get("system_origine"), | |
"Détenteur": item.get("detention", {}).get("detenteur"), | |
"Mode": item.get("detention", {}).get("mode"), | |
} | |
# Extract external references | |
ref_externes = item.get("ref_externes", {}).get("ref_externe", []) | |
if isinstance(ref_externes, dict): | |
ref_externes = [ref_externes] | |
if ref_externes: | |
systems = [ref.get("system") for ref in ref_externes] | |
row["Systèmes Externes"] = ", ".join(filter(None, systems)) | |
actifs_data.append(row) | |
actifs_df = pd.DataFrame(actifs_data) | |
if "Montant (EUR)" in actifs_df.columns: | |
try: | |
actifs_df["Montant (EUR)"] = pd.to_numeric( | |
actifs_df["Montant (EUR)"] | |
) | |
except ValueError: | |
print( | |
"Warning: Could not convert some actifs montants to numeric" | |
) | |
patrimoine_data["actifs"] = actifs_df | |
# Extract Passifs | |
if "passifs" in data["patrimoine"]: | |
passifs_items = data["patrimoine"]["passifs"].get("passif", []) | |
if isinstance(passifs_items, dict): | |
passifs_items = [passifs_items] | |
if passifs_items: | |
passifs_data = [] | |
for item in passifs_items: | |
row = { | |
"UUID": item.get("uuid"), | |
"Libellé": item.get("libelle"), | |
"Patrimoine ID": item.get("patrimoine_id"), | |
"Système": item.get("system_origine"), | |
"Souscripteur": item.get("souscripteur"), | |
"Périodicité": item.get("periodicite"), | |
"Taux HA": item.get("caracteristiques", {}).get("taux_HA"), | |
"Assurance Taux": item.get("assurance", {}).get("taux"), | |
"Capital Restant Dû (EUR)": item.get( | |
"capital_restant_du", {} | |
).get("montant_euro"), | |
"Date Capital Restant Dû": item.get( | |
"capital_restant_du", {} | |
).get("date"), | |
} | |
# Extract external references | |
ref_externes = item.get("ref_externes", {}).get("ref_externe", []) | |
if isinstance(ref_externes, dict): | |
ref_externes = [ref_externes] | |
if ref_externes: | |
systems = [ref.get("system") for ref in ref_externes] | |
row["Systèmes Externes"] = ", ".join(filter(None, systems)) | |
passifs_data.append(row) | |
passifs_df = pd.DataFrame(passifs_data) | |
if "Capital Restant Dû (EUR)" in passifs_df.columns: | |
try: | |
passifs_df["Capital Restant Dû (EUR)"] = pd.to_numeric( | |
passifs_df["Capital Restant Dû (EUR)"] | |
) | |
except ValueError: | |
print( | |
"Warning: Could not convert some passifs capital restant dû to numeric" | |
) | |
patrimoine_data["passifs"] = passifs_df | |
return patrimoine_data | |
def extract_budget(data): | |
budget_data = {"revenus": pd.DataFrame(), "charges": pd.DataFrame()} | |
if "budget" in data: | |
# Extract Revenus | |
if "revenus" in data["budget"]: | |
revenus_items = data["budget"]["revenus"].get("revenu", []) | |
if isinstance(revenus_items, dict): | |
revenus_items = [revenus_items] | |
if revenus_items: | |
revenus_data = [] | |
for item in revenus_items: | |
row = { | |
"ID": item.get("id"), | |
"Budget ID": item.get("budget_id"), | |
"Libellé": item.get("libelle"), | |
"Montant (EUR)": item.get("montant_euro"), | |
"Périodicité": item.get("periodicite"), | |
"Bénéficiaire": item.get("beneficiaire"), | |
"UUID": item.get("uuid"), | |
"Système": item.get("system_origine"), | |
"Date Terme": item.get("date_terme", ""), | |
} | |
# Extract external references if needed | |
ref_externes = item.get("ref_externes", {}).get("ref_externe", []) | |
if isinstance(ref_externes, dict): | |
ref_externes = [ref_externes] | |
if ref_externes: | |
systems = [ref.get("system") for ref in ref_externes] | |
row["Systèmes Externes"] = ", ".join(filter(None, systems)) | |
revenus_data.append(row) | |
revenus_df = pd.DataFrame(revenus_data) | |
if "Montant (EUR)" in revenus_df.columns: | |
try: | |
revenus_df["Montant (EUR)"] = pd.to_numeric( | |
revenus_df["Montant (EUR)"] | |
) | |
except ValueError: | |
print( | |
"Warning: Could not convert some revenus montants to numeric" | |
) | |
budget_data["revenus"] = revenus_df | |
# Extract Charges | |
if "charges" in data["budget"]: | |
charges_items = data["budget"]["charges"].get("charge", []) | |
if isinstance(charges_items, dict): | |
charges_items = [charges_items] | |
if charges_items: | |
charges_data = [] | |
for item in charges_items: | |
row = { | |
"ID": item.get("id"), | |
"Budget ID": item.get("budget_id"), | |
"Libellé": item.get("libelle"), | |
"Montant (EUR)": item.get("montant_euro"), | |
"Périodicité": item.get("periodicite"), | |
"Débiteur": item.get("debiteur"), | |
"UUID": item.get("uuid"), | |
"Système": item.get("system_origine"), | |
} | |
# Extract external references if needed | |
ref_externes = item.get("ref_externes", {}).get("ref_externe", []) | |
if isinstance(ref_externes, dict): | |
ref_externes = [ref_externes] | |
if ref_externes: | |
systems = [ref.get("system") for ref in ref_externes] | |
row["Systèmes Externes"] = ", ".join(filter(None, systems)) | |
charges_data.append(row) | |
charges_df = pd.DataFrame(charges_data) | |
if "Montant (EUR)" in charges_df.columns: | |
try: | |
charges_df["Montant (EUR)"] = pd.to_numeric( | |
charges_df["Montant (EUR)"] | |
) | |
except ValueError: | |
print( | |
"Warning: Could not convert some charges montants to numeric" | |
) | |
budget_data["charges"] = charges_df | |
return budget_data | |
def format_client_info(xml_file, client_id): | |
# Get JSON data using your previous function | |
json_data = client_to_json(xml_file, client_id) | |
tables = display_nested_json(json_data) | |
pd.set_option("display.max_columns", None) | |
pd.set_option("display.width", None) | |
pd.set_option( | |
"display.float_format", | |
lambda x: "{:.2f}".format(x) if isinstance(x, (float, int)) else x, | |
) | |
# Return DataFrames directly instead of string representations | |
outputs = [] | |
# Basic Info | |
outputs.append(gr.Markdown("## Client Basic Information")) | |
outputs.append(tables["basic_info"]) | |
# Contacts | |
outputs.append(gr.Markdown("## Contacts Client")) | |
outputs.append(tables["contacts"]) | |
# Accounts | |
outputs.append(gr.Markdown("## Accounts and Positions")) | |
outputs.append( | |
tables["accounts"] | |
if not tables["accounts"].empty | |
else pd.DataFrame({"Message": ["No accounts found"]}) | |
) | |
# Patrimoine - Actifs | |
outputs.append(gr.Markdown("## Patrimoine")) | |
outputs.append(gr.Markdown("### Actifs")) | |
outputs.append( | |
tables["patrimoine"]["actifs"] | |
if not tables["patrimoine"]["actifs"].empty | |
else pd.DataFrame({"Message": ["No actifs found"]}) | |
) | |
# Patrimoine - Passifs | |
outputs.append(gr.Markdown("### Passifs")) | |
outputs.append( | |
tables["patrimoine"]["passifs"] | |
if not tables["patrimoine"]["passifs"].empty | |
else pd.DataFrame({"Message": ["No passifs found"]}) | |
) | |
# Budget - Revenus | |
outputs.append(gr.Markdown("## Budget")) | |
outputs.append(gr.Markdown("### Revenus")) | |
outputs.append( | |
tables["budget"]["revenus"] | |
if not tables["budget"]["revenus"].empty | |
else pd.DataFrame({"Message": ["No revenus found"]}) | |
) | |
# Budget - Charges | |
outputs.append(gr.Markdown("### Charges")) | |
outputs.append( | |
tables["budget"]["charges"] | |
if not tables["budget"]["charges"].empty | |
else pd.DataFrame({"Message": ["No charges found"]}) | |
) | |
return outputs | |
# Create Gradio interface | |
with gr.Blocks(title="Client Information Viewer") as demo: | |
gr.Markdown("# Client Information Viewer") | |
gr.Markdown( | |
"Upload an XML file and select a client to view their detailed information" | |
) | |
xml_file = gr.File(label="Upload XML File", file_types=[".xml"]) | |
client_dropdown = gr.Dropdown(label="Select Client", choices=[], interactive=True) | |
view_btn = gr.Button("View Client Info", interactive=False) | |
# Create output containers for each section | |
basic_info_header = gr.Markdown() | |
basic_info_df = gr.DataFrame() | |
contacts_header = gr.Markdown() | |
contacts_df = gr.DataFrame() | |
accounts_header = gr.Markdown() | |
accounts_df = gr.DataFrame() | |
actifs_header = gr.Markdown() | |
actifs_subheader = gr.Markdown() | |
actifs_df = gr.DataFrame() | |
passifs_subheader = gr.Markdown() | |
passifs_df = gr.DataFrame() | |
revenus_header = gr.Markdown() | |
revenus_subheader = gr.Markdown() | |
revenus_df = gr.DataFrame() | |
charges_subheader = gr.Markdown() | |
charges_df = gr.DataFrame() | |
# Combine all outputs in order | |
output_dfs = [ | |
basic_info_header, | |
basic_info_df, | |
contacts_header, | |
contacts_df, | |
accounts_header, | |
accounts_df, | |
actifs_header, | |
actifs_subheader, | |
actifs_df, | |
passifs_subheader, | |
passifs_df, | |
revenus_header, | |
revenus_subheader, | |
revenus_df, | |
charges_subheader, | |
charges_df, | |
] | |
# Update dropdown when file is uploaded | |
def update_dropdown(file): | |
if file is None: | |
return gr.Dropdown(choices=[], value=None, interactive=False), gr.Button( | |
interactive=False | |
) | |
clients = get_clients_from_xml(file) | |
choices = [(name, id) for id, name in clients] | |
return gr.Dropdown(choices=choices, interactive=True), gr.Button( | |
interactive=True | |
) | |
xml_file.change( | |
fn=update_dropdown, inputs=[xml_file], outputs=[client_dropdown, view_btn] | |
) | |
# View client info when button is clicked | |
view_btn.click( | |
fn=format_client_info, | |
inputs=[xml_file, client_dropdown], | |
outputs=output_dfs, | |
) | |
if __name__ == "__main__": | |
demo.launch(server_port=7860, share=True) | |