From d4416f43c38b90e076248be7a9ee942819615778 Mon Sep 17 00:00:00 2001 From: Ladebeze66 Date: Wed, 19 Mar 2025 15:11:29 +0100 Subject: [PATCH] J6-3 --- .gitignore | 2 ++ __pycache__/menu_handlers.cpython-312.pyc | Bin 2720 -> 4075 bytes __pycache__/menu_principal.cpython-312.pyc | Bin 1351 -> 1680 bytes __pycache__/ticket_manager.cpython-312.pyc | Bin 8499 -> 10131 bytes menu_handlers.py | 21 ++++++++++++ menu_principal.py | 14 ++++++-- ticket_manager.py | 38 ++++++++++++++++++++- 7 files changed, 71 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 97f1089..f581bfe 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /odtkit +/exported_tickets +config.py \ No newline at end of file diff --git a/__pycache__/menu_handlers.cpython-312.pyc b/__pycache__/menu_handlers.cpython-312.pyc index e8a9f598022eb07e44f9db5017b06415d455fad3..4b6e9da55f85ea1a110067bf622898efbb9ba688 100644 GIT binary patch delta 1562 zcmZWpO>7%Q6yDh%@A_wrZG|RrLbIg}$p&f!YKRC?ewrVNl!im4ibANh^-hva*K0Go z+sct6=fI&zJtXX<5Jk8gP!N}*UMemi^#BqFoTgRNrKm#U#-&MaxxkyX^CNYnnSC?! z-uGtT_svva{A6w{S4=F?*gGtDy0B3fjR__AfR%II8~U1iqz z!?>F*JX7LJyehbTfHg8RW8~(rf*r-y+-rDNBRW=0O)(AI!HSM;C123*ubW`#hFvUJ z#uc#LW{8a_=L`Cad;NRtX=RU7`jsh__v4O{yNaD`UbD1WO#JvPOf=KX0xULdUnmm8 za(uyXaNbrqKeWFde0|>1^4LRMUnMoCS-Od{^k9u(l7v&xg4rL!u*Cc$w>_47Hsqd7 z`HiKCC!+jRl56qqhmyM0cH*0XuLf2JcNi2_zc_beeEH1NSaSL7vb#Kc>q51u8mgtb z9>u!1IoN+LFj9OMAekH;f)f=$ga3f4kG z>E5^NN%xTIGla58XnlR29zYF&BCMhd!Y~WhF(I_jejC+Jpo{E`flb}cUN@Y%Y=uVH zBuXJ-FsOnbse4iJ_@TP5F9ctoH>{b0FYg~BOQ$xyVhU{}K@+vSptVLqasswrf^L5c z11K(etkzulXft_fX>vk1qx(LQr<|Y^~ZZU5(uTp>tG85BoJU4ranh+U*w`@x_F$B z0wJ^%^>Qa@xf|E_N-1mTL5aOT*^F2(Q`-AkXpvyO2V&aqUgDl1k>;2pC%qxz?dU-k z686eM%WDBc6klciXahJ0&j3+j&4wooI3Nk{C*f5g1CxyRw{V#yskq1v{S-L+{8e1C>!kW4b@4()BUN-z|B@+AT}=_ gJA4SKJBcV7Mmy;Q8bdpYQ&Dsd?WUX2C<-wD2lsEVH~;_u delta 451 zcmY*UO-lk%6rHP%GtD%kXl6#Cg;^39w2X?PT13>cjg*W!$mBR<*D-Su^bblN?c28Y zN3`e{^dQ=`Y17B9P2DjedhibC-t+D`_r0cX6Z(UuDFU7Ei^tlc+|wsuqc^`9>W1@D z?|iF29d1C7!zsIx+ho?Rk_$inq(_-fh7V<%#o+WF`AV6SMoDR643*cSzB4&9U+eXdZ-cb*ng{v zTQxD_tA21kz|~>QK!{PV6(GoDFwWkTS#g4j6icedflq;H;Z*-xeF2bIM=P!k{KtKN zTj@{_@K^ZkxicB8) zUqe3{eeF)bl+WV?U-D|ht+s7*9kWyd-Bym^EeHTl!ossqcn=G)G)rIVAE790!$($y NJ@}kV!WImCegNu&cM1Ri diff --git a/__pycache__/menu_principal.cpython-312.pyc b/__pycache__/menu_principal.cpython-312.pyc index 8b577366709d46e17f2b3697916e1f9a4f320989..a8fc52a3b0fc6f7824c0465ec654e5f6cf26432f 100644 GIT binary patch delta 772 zcmZWmPiqrF6rb6h-6We$Y%8UylxD^HClY%wZKS1WMe4;;5QSp2gqYcw#obMr*+m+J zUOb3+XxM{aLFvhUg$g1<37CQ|`2vE6+9CzL_-0Ks;Dh0bh7X4<%3t69~$$qc(ZiOTvpX}S_RW=TUsLf9S9LN~sV@bu*4+L;Hl)y7bnGw8%quAdF CO|ppq delta 431 zcmYjLJxc>Y5S_W*yNj30iHVY^fmkSbkVZ%vjUR=!S||u7k|G;a%q6gw6cJ0Yvhdi# zM(_t%3jPHP!B$K!#7<2ivC-WN5eMGm&Cbr7cbRywoX14M0$Kg*mxB%ooy@|l?5=zizrj?3{8Mio4+u)kw z9-qjGRS;cm4hzB|`<5-IrbMtPS|l&-NRp~-VK*yYNfAq8n&vPsmS}D{dkTym&jWC~ zIWjN>VEXU?LficJ{&yJRV%Lp{XId0VeRW;u>LgbQIaQ=9QW0G27?s1uQKcHF%riVL zxfA29dfBhmTRbJ(F^OPD+~{kfucz!uh>voWchfaQ#>j0&-s&S)38PVD^BpVs4c4kv hSNMb+DF0we(mO%KFO8!10g^s#6AQg@2RAU<{RPqxP96XN diff --git a/__pycache__/ticket_manager.cpython-312.pyc b/__pycache__/ticket_manager.cpython-312.pyc index 168035179d438084a3abd4bbfa21f72caafe8823..c5f99518a60154e478b350a782c290a887b7a16e 100644 GIT binary patch delta 1883 zcmZ{kUrZE79LHyN_m(~GKX7+)9IzrSp45|=rq)=kq78ze6@eOxJ=fdqv3lHHW_Puc zqgN9XNoyizUNo(d`ULTX=3Z#hm`iwQleWoHNWrTQeeO#^+cfp5GkbSAtnDQC-I@9Q zncvNPX7b(ml>2*^s}_*<_7BCxcJV8BJ%ppU4eo*-JOJChvhz9^b;~ZIo~!PNH*Y{i zfPdzHvG3*ZeZQZ11hC14u<37Xbm}b4M4N1T2unQ(uJV`*?6gg>Q%n|LbNF*vR<3!- zRLpu!sYil@YEYIv1L6!MzbWPlh}exciPzxLeB8(^%_9YgiY{uBaal=7NG3x)ZD?Xr z(Zq?gyfjBUvZ`g$DfI&BPYNoE5`&T~IyA*Eq4;y0*SLUg7 zQ#nW^!sU>Ue2aW(DXY4oqcn)gYFyViVirk5b=1$DQ1n=}w8`+08o#9I15!##C@A`( z^$3a3J|gl7_|@lM^X*vn?U?Oba4n)j&vzr{(V-RJNN$>c?D0Qw2F-1KtIiYa^}!7u z9EH8`=RohGf5y1;-tCWPjk%F8r7>8c-B^? zm1LV@39l}L?su8jIi$RZs|9L&T$;!bOgoHJ8QPp8N|%*5u^LDd^{W|0L+vC@gtZt& zuabUIKuS{5)pQDVkfAk)dP(nOgsBdSH6N-_$jfm5kL$Z6uT~&JNDqY80y~!jJLf_RV}-px^~6^K^0eczCqy9+9V?6$ z`ps>pSDl0F_5SHx?}itMoolUK%dK52t$Y7+@WI;6THp)M*k<$%J8;#lZwucUx$9gH zi}#P;Jw7|S(6ADIW7EbqxHkdoa&NFCV%o6@$Y-N&%e`0#E`}DJg?G$7eXGI=>wfH> zyEr#y?jJTs&YQ!MDJ9G%_xP%ymha57Ajx4}nQwMo#&okpkek9Ds>lz(3L0Jfba{wL8X8bx=m@-|t= zXC3M=e$IwQKG&qev-sPl&zgtHM3I*=86_o` z&={pI?^7AW>9BvmDs~?o(?=ccCsGt9q)UpdA`NkL&Uz1hC6F%Bi3?QX)U!snUO5d7 z(y1Z59Nq^fu)XPs>31NanJAIt3@ DA&&o_ delta 511 zcmX}pJ4+)`6bJAe8Do4T5)HxlVjW|2e1e5<0})p-n5dwrjWT4e8jTO`B!xCUu(Oi$ z4eTuS7GiI=+u3D5z?KVZXQTH&f*0mDhyOV<+&jZdY9{n67_9N>m3k@f{*FC_8i}%O zQZEHLLviD@&I+kZ5&k&Ii?MD)v`#z za;+-;t*bH<~x+X&sdP_Q{Dja-@as5?BT+=+(HQ z=!hM=R47VpPf`^2Lj2J+og6~<>s+Yjz$VxRCC$B0Mo@d73jas~T<$nuC*u5=nDl$w noZz>_eDfJbzMpsxOdTFOrGiMx3tsIW45uq-i~jq(n>Y3eSfO&= diff --git a/menu_handlers.py b/menu_handlers.py index 8d2dc13..d44e421 100644 --- a/menu_handlers.py +++ b/menu_handlers.py @@ -4,6 +4,27 @@ from utils import get_user_choice, print_error # Initialisation de l'objet ticket_manager = TicketManager() +def handle_list_models(): + """Affiche et sauvegarde la liste des modèles disponibles""" + models = ticket_manager.get_all_models() + if models: + print("\n Modèles disponibles:") + for model, name in models.items(): + print(f"- {model} : {name}") + +def handle_list_model_fields(): + """Demande à l'utilisateur un modèle et affiche ses champs avec leur type.""" + model_name = input("\nEntrez le nom du modèle à inspecter (ou 'q' pour quitter): ") + if model_name.lower() == 'q': + return + + fields = ticket_manager.get_model_fields_with_types(model_name) + if fields: + print(f"\nChamps du modèle '{model_name}':") + for field, info in fields.items(): + relation_info = f" (relation avec {info['relation']})" if info["relation"] else "" + print(f"- {field} : {info['type']}{relation_info}") + def handle_search_ticket_by_id(): """Gère la recherche d'un ticket par ID""" ticket_id_input = input("Entrez l'ID du ticket(ou 'q' pour quitter): ") diff --git a/menu_principal.py b/menu_principal.py index da38d13..9e8d7c6 100644 --- a/menu_principal.py +++ b/menu_principal.py @@ -1,7 +1,9 @@ from menu_handlers import ( handle_project_tickets_by_stage, handle_search_ticket_by_id, - handle_search_ticket_by_code + handle_search_ticket_by_code, + handle_list_models, + handle_list_model_fields ) def display_main_menu(): @@ -10,8 +12,10 @@ def display_main_menu(): print("1. Exporter les tickets d'un project_id par étape") print("2. Rechercher un ticket par ID") print("3. Rechercher un ticket par Code") - print("4. Quitter") - return input("\nChoisissez une option (1-4): ") + print("4. Afficher la liste des modèles disponibles") + print("5. Afficher les champs d'un modèle donné") + print("6. Quitter") + return input("\nChoisissez une option (1-6): ") def run_menu(): @@ -25,6 +29,10 @@ def run_menu(): elif choice == '3': handle_search_ticket_by_code() elif choice == '4': + handle_list_models() + elif choice == '5': + handle_list_model_fields() + elif choice == '6': print("Au revoir!") break else: diff --git a/ticket_manager.py b/ticket_manager.py index 464200a..2bb0eb0 100644 --- a/ticket_manager.py +++ b/ticket_manager.py @@ -61,7 +61,43 @@ class TicketManager: with open(file_path, "w", encoding="utf-8") as f: json.dump(ticket_data, f, indent=4, ensure_ascii=False) print(f"Données brutes du ticket sauvegardées dans : {file_path}") + + def get_all_models(self): + """Récupérer et sauvegarder tous les modèles disponibles""" + models = self._safe_execute('ir.model', 'search_read', [], ['model', 'name'] ) + if not models: + print_error("Impossible de récupérer la liste des modèles.") + return None + #Convertir en dictionnaire {nom_du_modèle: description} + models_dict = {model['model']: model['name'] for model in models} + + #Sauvegarder dans un fichier JSON + self.save_raw_ticket_data(models_dict, "all_models.json") + print(f"Liste des modèles sauvegardée dans 'available_models.json") + return models_dict + + def get_model_fields_with_types(self, model_name): + """Récupère et sauvegarde les champs d'un modèle avec leurs types""" + fields_info = self._safe_execute(model_name, 'fields_get', [], ['name', 'type', 'relation']) + if not fields_info: + print_error(f"Impossible de récupérer les champs pour {model_name}") + return {} + + # Construire un dictionnaire {champ: {type, relation (si relationnel)}} + fields_dict = { + field: { + "type": info["type"], + "relation": info.get("relation", None) + } + for field, info in fields_info.items() + } + + # Sauvegarde en JSON + self.save_raw_ticket_data(fields_dict, f"fields_{model_name}.json") + print(f"Liste des champs du modèle '{model_name}' sauvegardée dans 'fields_{model_name}.json'") + return fields_dict + def get_ticket_by_id(self, ticket_id): """Récupère les détails d'un ticket par son ID et exclut dynamiquement les champs invalides""" fields_to_read = self.get_model_fields(self.model_name) # Récupère tous les champs @@ -79,7 +115,7 @@ class TicketManager: """Ajoute les valeurs des champs relationnels""" fields_info = self._safe_execute(self.model_name, 'fields_get', [], ['type']) - for field, info in fields_info.items(): + for field, info in fields_info.items(): # type: ignore if info.get("type") == "many2one" and isinstance(ticket.get(field), list): ticket[f"{field}_value"] = ticket[field][1] if len(ticket[field]) > 1 else None #Ajoute la valeur lisible en plus du ID return ticket