gael_explorer / app.py
AdrienB134's picture
Update app.py
004db5f verified
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)