350 lines
13 KiB
Python
350 lines
13 KiB
Python
from typing import List
|
|
import streamlit as st
|
|
from utils.translations import _
|
|
import networkx as nx
|
|
from utils.persistance import supprime_champ_statut, get_champ_statut, maj_champ_statut
|
|
|
|
def get_produits_personnalises(
|
|
G: nx.DiGraph
|
|
) -> List[str]:
|
|
"""
|
|
Récupère la liste des produits personnalisés du niveau 0.
|
|
|
|
Args:
|
|
G (Any): Le graphe NetworkX contenant les données des produits.
|
|
|
|
Returns:
|
|
List[str]: Liste triée des noms de produits.
|
|
"""
|
|
return sorted([n for n, d in G.nodes(data=True) if d.get("niveau") == "0" and d.get("personnalisation") == "oui"])
|
|
|
|
def supprimer_produit(
|
|
G: nx.DiGraph,
|
|
prod: str
|
|
) -> nx.DiGraph:
|
|
"""
|
|
Supprime un produit du graphe et affiche le message de succès.
|
|
|
|
Args:
|
|
G (Any): Le graphe NetworkX sur lequel supprimer le produit.
|
|
prod (str): Le nom du produit à supprimer.
|
|
"""
|
|
G.remove_node(prod)
|
|
st.success(f"{prod} {str(_('pages.personnalisation.deleted'))}")
|
|
st.session_state.pop("prod_sel", None)
|
|
st.rerun()
|
|
return G
|
|
|
|
def get_operations_disponibles(
|
|
G: nx.DiGraph
|
|
) -> List[str]:
|
|
"""
|
|
Récupère la liste des opérations d'assemblage disponibles.
|
|
|
|
Args:
|
|
G (Any): Le graphe NetworkX contenant les données des produits et des opérations.
|
|
|
|
Returns:
|
|
List[str]: Liste triée des noms des opérations.
|
|
"""
|
|
return sorted([
|
|
n for n, d in G.nodes(data=True)
|
|
if d.get("niveau") == "10"
|
|
and any(G.has_edge(p, n) and G.nodes[p].get("niveau") == "0" for p in G.predecessors(n))
|
|
])
|
|
|
|
def get_operations_actuelles(
|
|
G: nx.DiGraph,
|
|
prod: str
|
|
) -> List[str]:
|
|
"""
|
|
Récupère les opérations actuellement liées au produit.
|
|
|
|
Args:
|
|
G (nx.DiGraph): Le graphe NetworkX contenant les données des produits et des opérations.
|
|
prod (str): Le nom du produit dont récupérer les opérations.
|
|
|
|
Returns:
|
|
List[str]: Liste des noms des opérations actuelles.
|
|
"""
|
|
return [succ for succ in G.successors(prod) if G.nodes[succ].get("niveau") == "10"]
|
|
|
|
def get_composants_niveau1(
|
|
G: nx.DiGraph
|
|
) -> List[str]:
|
|
"""
|
|
Récupère la liste des composants de niveau 1.
|
|
|
|
Args:
|
|
G (nx.DiGraph): Le graphe NetworkX contenant les données des produits et des composants.
|
|
|
|
Returns:
|
|
List[str]: Liste triée des noms des composants.
|
|
"""
|
|
return sorted([n for n, d in G.nodes(data=True) if d.get("niveau") == "1"])
|
|
|
|
def get_composants_lies(
|
|
G: nx.DiGraph,
|
|
prod: str
|
|
) -> List[str]:
|
|
"""
|
|
Récupère les composants actuellement liés au produit.
|
|
|
|
Args:
|
|
G (nx.DiGraph): Le graphe NetworkX contenant les données des produits et des composants.
|
|
prod (str): Le nom du produit dont récupérer les composants.
|
|
|
|
Returns:
|
|
List[str]: Liste des noms des composants liés.
|
|
"""
|
|
return [succ for succ in G.successors(prod) if G.nodes[succ].get("niveau") == "1"]
|
|
|
|
def mettre_a_jour_operations(
|
|
G: nx.DiGraph,
|
|
prod: str,
|
|
curr_ops: List[str],
|
|
sel_op: str
|
|
) -> nx.DiGraph:
|
|
"""
|
|
Met à jour les opérations liées au produit.
|
|
|
|
Args:
|
|
G (Any): Le graphe NetworkX contenant les données des produits et des opérations.
|
|
prod (str): Le nom du produit dont mettre à jour les opérations.
|
|
curr_ops (List[str]): Liste actuelle des opérations liées.
|
|
sel_op (str): L'opération sélectionnée pour mise à jour.
|
|
|
|
Notes:
|
|
Cette fonction crée ou supprime les liens entre le produit et les opérations
|
|
selon la sélection effectuée par l'utilisateur.
|
|
"""
|
|
|
|
none_option = str(_("pages.personnalisation.none"))
|
|
for op in curr_ops:
|
|
if sel_op == none_option or op != sel_op:
|
|
G.remove_edge(prod, op)
|
|
if sel_op != none_option and (not curr_ops or sel_op not in curr_ops):
|
|
G.add_edge(prod, sel_op)
|
|
return G
|
|
|
|
def mettre_a_jour_composants(
|
|
G: nx.DiGraph,
|
|
prod: str,
|
|
linked: List[str],
|
|
nouveaux: List[str]
|
|
) -> nx.DiGraph:
|
|
"""
|
|
Met à jour les composants liés au produit.
|
|
|
|
Args:
|
|
G (nx.DiGraph): Le graphe NetworkX contenant les données des produits et des composants.
|
|
prod (str): Le nom du produit dont mettre à jour les composants.
|
|
linked (List[str]): Liste actuelle des composants liés.
|
|
nouveaux (List[str]): Nouvelle liste de composants à lier.
|
|
|
|
Notes:
|
|
Cette fonction crée ou supprime les liens entre le produit et les composants
|
|
selon la sélection effectuée par l'utilisateur.
|
|
"""
|
|
"""Met à jour les composants liés au produit."""
|
|
for comp in set(linked) - set(nouveaux):
|
|
G.remove_edge(prod, comp)
|
|
for comp in set(nouveaux) - set(linked):
|
|
G.add_edge(prod, comp)
|
|
return G
|
|
|
|
def modifier_produit(
|
|
G: nx.DiGraph
|
|
) -> nx.DiGraph:
|
|
"""
|
|
Méthode de personnalisation qui permet à l'utilisateur d'ajuster un produit.
|
|
|
|
Args:
|
|
G (Any): Le graphe NetworkX sur lequel modifier les produits et leurs composants.
|
|
Contient des données concernant la personalisation des produits,
|
|
leur niveau, et les opérations liées.
|
|
|
|
Notes:
|
|
Cette fonction fournit une interface utilisateur pour sélectionner
|
|
un produit à personnaliser, gérer ses composants, et définir ses opérations
|
|
d'assemblage. Elle implémente la logique de mise à jour des connexions entre
|
|
les différents éléments du graphe.
|
|
"""
|
|
st.markdown(f"## {str(_('pages.personnalisation.modify_product'))}")
|
|
|
|
# Restauration des produits personnalisés sauvegardés
|
|
if "pages.personnalisation.create_product.fait" not in st.session_state and get_champ_statut("pages.personnalisation.create_product.fait") == "oui":
|
|
index = 0
|
|
while True:
|
|
new_prod = get_champ_statut(f"pages.personnalisation.create_product.{index}.nom")
|
|
if new_prod == "":
|
|
break
|
|
|
|
G.add_node(new_prod, niveau="0", personnalisation="oui", label=new_prod)
|
|
|
|
sel_new_op = get_champ_statut(f"pages.personnalisation.create_product.{index}.edge")
|
|
if sel_new_op:
|
|
G.add_edge(new_prod, sel_new_op)
|
|
|
|
i = 0
|
|
while True:
|
|
comp = get_champ_statut(f"pages.personnalisation.create_product.{index}.composants.{i}")
|
|
if comp == "":
|
|
break
|
|
G.add_edge(new_prod, comp)
|
|
i += 1
|
|
|
|
index += 1
|
|
|
|
st.session_state["pages.personnalisation.create_product.fait"] = "oui"
|
|
|
|
# Sélection du produit à modifier
|
|
produits0 = get_produits_personnalises(G)
|
|
|
|
# Restaurer la sélection du produit depuis la persistance
|
|
if "pages.personnalisation.modify.selected_product" not in st.session_state:
|
|
st.session_state["pages.personnalisation.modify.selected_product"] = get_champ_statut("pages.personnalisation.modify.selected_product")
|
|
|
|
sel_display = st.selectbox(
|
|
label=str(_("pages.personnalisation.products_to_modify")),
|
|
options=produits0,
|
|
key="pages.personnalisation.modify.selected_product"
|
|
)
|
|
|
|
if sel_display:
|
|
maj_champ_statut("pages.personnalisation.modify.selected_product", sel_display)
|
|
|
|
if not sel_display:
|
|
return G
|
|
|
|
# Obtention du produit sélectionné
|
|
prod = sel_display
|
|
|
|
# Trouver l'index du produit dans la sauvegarde
|
|
index_key = None
|
|
index = 0
|
|
while True:
|
|
saved_name = get_champ_statut(f"pages.personnalisation.create_product.{index}.nom")
|
|
if saved_name == "":
|
|
break
|
|
if saved_name == prod:
|
|
index_key = index
|
|
break
|
|
index += 1
|
|
|
|
# Suppression du produit si demandé
|
|
if st.button(f"{str(_('pages.personnalisation.delete'))} {prod}"):
|
|
if index_key is not None:
|
|
# Supprimer les données du produit
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.nom")
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.edge")
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.composants")
|
|
# Réorganiser les indices pour combler le trou
|
|
next_index = index_key + 1
|
|
while get_champ_statut(f"pages.personnalisation.create_product.{next_index}.nom") != "":
|
|
# Déplacer le produit suivant vers l'index actuel
|
|
nom = get_champ_statut(f"pages.personnalisation.create_product.{next_index}.nom")
|
|
edge = get_champ_statut(f"pages.personnalisation.create_product.{next_index}.edge")
|
|
|
|
maj_champ_statut(f"pages.personnalisation.create_product.{next_index - 1}.nom", nom)
|
|
if edge:
|
|
maj_champ_statut(f"pages.personnalisation.create_product.{next_index - 1}.edge", edge)
|
|
else:
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{next_index - 1}.edge")
|
|
|
|
# Copier les composants
|
|
i = 0
|
|
while True:
|
|
comp = get_champ_statut(f"pages.personnalisation.create_product.{next_index}.composants.{i}")
|
|
if comp == "":
|
|
break
|
|
maj_champ_statut(f"pages.personnalisation.create_product.{next_index - 1}.composants.{i}", comp)
|
|
i += 1
|
|
|
|
# Supprimer l'ancien emplacement
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{next_index}")
|
|
next_index += 1
|
|
# Nettoyer aussi les champs de modification
|
|
supprime_champ_statut("pages.personnalisation.modify")
|
|
if "pages.personnalisation.modify.selected_product" in st.session_state:
|
|
del st.session_state["pages.personnalisation.modify.selected_product"]
|
|
if "pages.personnalisation.modify.selected_operation" in st.session_state:
|
|
del st.session_state["pages.personnalisation.modify.selected_operation"]
|
|
if "pages.personnalisation.modify.selected_components" in st.session_state:
|
|
del st.session_state["pages.personnalisation.modify.selected_components"]
|
|
return supprimer_produit(G, prod)
|
|
|
|
# Gestion des opérations d'assemblage
|
|
ops_dispo = get_operations_disponibles(G)
|
|
curr_ops = get_operations_actuelles(G, prod)
|
|
|
|
# Restaurer la sélection de l'opération depuis la persistance
|
|
if "pages.personnalisation.modify.selected_operation" not in st.session_state:
|
|
saved_op = get_champ_statut("pages.personnalisation.modify.selected_operation")
|
|
if saved_op and saved_op in [str(_("pages.personnalisation.none"))] + ops_dispo:
|
|
st.session_state["pages.personnalisation.modify.selected_operation"] = saved_op
|
|
else:
|
|
default_op = curr_ops[0] if curr_ops else str(_("pages.personnalisation.none"))
|
|
st.session_state["pages.personnalisation.modify.selected_operation"] = default_op
|
|
|
|
sel_op = st.selectbox(
|
|
str(_("pages.personnalisation.linked_assembly_operation")),
|
|
[str(_("pages.personnalisation.none"))] + ops_dispo,
|
|
key="pages.personnalisation.modify.selected_operation"
|
|
)
|
|
|
|
if sel_op:
|
|
maj_champ_statut("pages.personnalisation.modify.selected_operation", sel_op)
|
|
|
|
# Gestion des composants
|
|
niveau1 = get_composants_niveau1(G)
|
|
linked = get_composants_lies(G, prod)
|
|
|
|
# Restaurer la sélection des composants depuis la persistance
|
|
if "pages.personnalisation.modify.selected_components" not in st.session_state:
|
|
saved_comps = []
|
|
i = 0
|
|
while True:
|
|
comp = get_champ_statut(f"pages.personnalisation.modify.selected_components.{i}")
|
|
if comp == "":
|
|
break
|
|
if comp in niveau1:
|
|
saved_comps.append(comp)
|
|
i += 1
|
|
st.session_state["pages.personnalisation.modify.selected_components"] = saved_comps if saved_comps else linked
|
|
|
|
nouveaux = st.multiselect(
|
|
f"{str(_('pages.personnalisation.components_linked_to'))} {prod}",
|
|
options=niveau1,
|
|
key="pages.personnalisation.modify.selected_components"
|
|
)
|
|
|
|
if nouveaux:
|
|
supprime_champ_statut("pages.personnalisation.modify.selected_components")
|
|
for i, comp in enumerate(nouveaux):
|
|
maj_champ_statut(f"pages.personnalisation.modify.selected_components.{i}", comp)
|
|
|
|
# Mise à jour des liens si demandé
|
|
if st.button(f"{str(_('pages.personnalisation.update'))} {prod}"):
|
|
G = mettre_a_jour_operations(G, prod, curr_ops, sel_op)
|
|
if index_key is not None:
|
|
if sel_op != str(_("pages.personnalisation.none")):
|
|
maj_champ_statut(f"pages.personnalisation.create_product.{index_key}.edge", sel_op)
|
|
else:
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.edge")
|
|
|
|
G = mettre_a_jour_composants(G, prod, linked, nouveaux)
|
|
if index_key is not None:
|
|
if nouveaux:
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.composants")
|
|
for j, comp in enumerate(nouveaux):
|
|
maj_champ_statut(f"pages.personnalisation.create_product.{index_key}.composants.{j}", comp)
|
|
else:
|
|
supprime_champ_statut(f"pages.personnalisation.create_product.{index_key}.composants")
|
|
|
|
st.success(f"{prod} {str(_('pages.personnalisation.updated'))}")
|
|
# Forcer la sauvegarde de l'état
|
|
maj_champ_statut("pages.personnalisation.create_product.fait", "oui")
|
|
|
|
return G
|