diff --git a/datas/adefpat_archi_dossier_datas.xml b/datas/adefpat_archi_dossier_datas.xml index 8dca430fd6f316336a7445a51a2f2a80bf1ae9b5..31c8aa8af429ba936f4a75d01986f645ffbcca50 100644 --- a/datas/adefpat_archi_dossier_datas.xml +++ b/datas/adefpat_archi_dossier_datas.xml @@ -1,57 +1,61 @@ <odoo> <data noupdate="1"> + <!-- PARENTS--> <record id="adefpat_archi_dossier_1" model="adefpat.archi.dossier"> <field name="name">admin</field> - <field name="path">nom_projet/admin/</field> </record> <record id="adefpat_archi_dossier_2" model="adefpat.archi.dossier"> <field name="name">beneficiaires</field> - <field name="path">nom_projet/beneficiaires/</field> - </record> - <record id="adefpat_archi_dossier_3" model="adefpat.archi.dossier"> - <field name="name">nom_benef</field> - <field name="path">nom_projet/beneficiaires/nom_benef/</field> - <field name="specifique">1</field> - </record> - <record id="adefpat_archi_dossier_4" model="adefpat.archi.dossier"> - <field name="name">malette</field> - <field name="path">nom_projet/beneficiaires/nom_benef/malette/</field> - <field name="specifique">1</field> </record> <record id="adefpat_archi_dossier_5" model="adefpat.archi.dossier"> <field name="name">comm</field> - <field name="path">nom_projet/comm/</field> </record> <record id="adefpat_archi_dossier_6" model="adefpat.archi.dossier"> <field name="name">consultation</field> - <field name="path">nom_projet/consultation/</field> - </record> - <record id="adefpat_archi_dossier_7" model="adefpat.archi.dossier"> - <field name="name">nom_CF</field> - <field name="path">nom_projet/consultation/nom_CF/</field> - <field name="specifique">1</field> </record> <record id="adefpat_archi_dossier_8" model="adefpat.archi.dossier"> <field name="name">financement</field> - <field name="path">nom_projet/financement</field> </record> <record id="adefpat_archi_dossier_9" model="adefpat.archi.dossier"> <field name="name">gap</field> - <field name="path">nom_projet/gap/</field> - </record> - <record id="adefpat_archi_dossier_10" model="adefpat.archi.dossier"> - <field name="name">date_gap</field> - <field name="path">nom_projet/gap/date_gap/</field> - <field name="specifique">1</field> </record> <record id="adefpat_archi_dossier_11" model="adefpat.archi.dossier"> <field name="name">malette_formateur</field> - <field name="path">nom_projet/malette_formateur/</field> </record> <record id="adefpat_archi_dossier_12" model="adefpat.archi.dossier"> <field name="name">seances</field> - <field name="path">nom_projet/seances/</field> </record> + <!-- Niveau 1 --> + <record id="adefpat_archi_dossier_10" model="adefpat.archi.dossier"> + <field name="name">date_gap</field> + <field name="specifique">1</field> + <field name="parent_id" ref="adefpat_alfodoo.adefpat_archi_dossier_9"/> + <field name="model_id" ref="adefpat_project.model_adefpat_reunion_gap" /> + </record> + <record id="adefpat_archi_dossier_7" model="adefpat.archi.dossier"> + <field name="name">nom_CF</field> + <field name="specifique">1</field> + <field name="parent_id" ref="adefpat_alfodoo.adefpat_archi_dossier_6"/> + <field name="model_id" ref="adefpat_project.model_res_partner_consultants_project" /> + </record> + <record id="adefpat_archi_dossier_3" model="adefpat.archi.dossier"> + <field name="name">nom_benef</field> + <field name="specifique">1</field> + <field name="parent_id" ref="adefpat_alfodoo.adefpat_archi_dossier_2"/> + <field name="model_id" ref="adefpat_project.model_res_partner_porteur_project" /> + </record> + + <!-- Niveau 2 --> + <record id="adefpat_archi_dossier_4" model="adefpat.archi.dossier"> + <field name="name">malette</field> + <field name="parent_id" ref="adefpat_alfodoo.adefpat_archi_dossier_3"/> + </record> + + + + + + </data> </odoo> diff --git a/models/adefpat_list_type_doc.py b/models/adefpat_list_type_doc.py index 649df9dab4302a38ed81bbdeb33a33ba692bbedd..581b51ed1ef43f46766bdcf939f9a1a680e6d5db 100644 --- a/models/adefpat_list_type_doc.py +++ b/models/adefpat_list_type_doc.py @@ -1,6 +1,8 @@ # Copyright 2020 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import models, fields + +from odoo import models, fields, api +from odoo.exceptions import ValidationError class ProjectProject(models.Model): @@ -30,11 +32,54 @@ class AdefpatListTypeDoc(models.Model): class AdefpatArchiDossier(models.Model): _name = 'adefpat.archi.dossier' _description = 'Architecture des dossiers' + _parent_name = "parent_id" + _parent_store = True + _rec_name = 'path' + _order = 'path' - name = fields.Char("Nom du dossier") - path = fields.Char("Path") + name = fields.Char("Nom du dossier", required=True) + path = fields.Char( + string="Path", + compute="_compute_path", + store=True + ) parent_id = fields.Many2one( 'adefpat.archi.dossier', string='Parent', index=True) + child_ids = fields.One2many( + comodel_name='adefpat.archi.dossier', + inverse_name='parent_id', + string='Dossiers enfants') + parent_path = fields.Char(index=True) specifique = fields.Boolean("Dossier spécifique") + model_id = fields.Many2one( + comodel_name="ir.model", + string="Table associée" + ) + + # ------------------------------------------------------ + # Compute Functions + # ------------------------------------------------------ + @api.depends('name', 'parent_id', 'parent_id.name') + @api.multi + def _compute_path(self): + for dossier in self: + path_list = [] + current = dossier + if dossier.name: + while current: + path_list.append(current.name) + current = current.parent_id + dossier.path = '/'.join(reversed(path_list)) + '/' + + # ------------------------------------------------------ + # Constrain Functions + # ------------------------------------------------------ + @api.constrains('parent_id') + def _check_folder_recursion(self): + if not self._check_recursion(): + raise ValidationError( + 'Vous ne pouvez pas créer des catégories récusrives.') + return True + diff --git a/models/project.py b/models/project.py index 49baf0cf7968ae0acaa6b9e85422fe99519b6526..a9fcdf529db960c236bbf5aaf99f0d0d3114b3c4 100644 --- a/models/project.py +++ b/models/project.py @@ -12,13 +12,13 @@ from odoo.addons.cmis_field import fields class AdefpatPorteursProjets(models.Model): _inherit = 'res.partner.porteur.project' - pp_cmis_folder = fields.CmisFolder( + cmis_folder = fields.CmisFolder( allow_create=True, allow_delete=False, create_properties_get='_get_folder_properties', ) - pp_cmis_folder_completion = odooFields.Selection( + cmis_folder_completion = odooFields.Selection( [(9, 'Inconnu'), (0, 'Incomplet'), (1, 'Complet'), @@ -28,11 +28,11 @@ class AdefpatPorteursProjets(models.Model): @api.multi def get_content_details_url(self): for pp in self: - if pp.pp_cmis_folder: - backend_name = self._fields['pp_cmis_folder'] + if pp.cmis_folder: + backend_name = self._fields['cmis_folder'] backend = backend_name.get_backend(pp.env) properties = backend.get_cmis_repository().getFolder( - pp.pp_cmis_folder).getProperties() + pp.cmis_folder).getProperties() url = backend.get_content_details_url_from_props(properties) return { 'type': 'ir.actions.act_url', @@ -67,15 +67,16 @@ class AdefpatPorteursProjets(models.Model): @api.multi def _get_completion_status(self): for pp in self: - if pp.pp_cmis_folder: - backend_name = self._fields['pp_cmis_folder'] + if pp.cmis_folder: + backend_name = self._fields['cmis_folder'] backend = backend_name.get_backend(pp.env) - pp.pp_cmis_folder_completion = backend.get_cmis_repository().getFolder(pp.pp_cmis_folder).getProperties()['adefpat:validationStatut'] or 9 + pp.cmis_folder_completion = backend.get_cmis_repository().getFolder(pp.cmis_folder).getProperties()['adefpat:validationStatut'] or 9 + class AdefpatConsultantsProjets(models.Model): _inherit = 'res.partner.consultants.project' - consult_cmis_folder = fields.CmisFolder( + cmis_folder = fields.CmisFolder( allow_create=True, allow_delete=False, create_properties_get='_get_folder_properties', @@ -84,8 +85,8 @@ class AdefpatConsultantsProjets(models.Model): @api.multi def get_content_details_url(self): for pp in self: - if pp.consult_cmis_folder: - backend_name = self._fields['consult_cmis_folder'] + if pp.cmis_folder: + backend_name = self._fields['cmis_folder'] folder = backend_name.get_cmis_object(pp) backend = backend_name.get_backend(pp.env) repo = backend.get_cmis_repository() @@ -120,7 +121,7 @@ class AdefpatConsultantsProjets(models.Model): class AdefpatReunionGAP(models.Model): _inherit = 'adefpat.reunion.gap' - gap_cmis_folder = fields.CmisFolder( + cmis_folder = fields.CmisFolder( allow_create=True, allow_delete=False, create_properties_get='_get_folder_properties', @@ -151,8 +152,8 @@ class AdefpatReunionGAP(models.Model): @api.multi def get_content_details_url(self): for pp in self: - if pp.gap_cmis_folder: - backend_name = self._fields['gap_cmis_folder'] + if pp.cmis_folder: + backend_name = self._fields['cmis_folder'] folder = backend_name.get_cmis_object(pp) backend = backend_name.get_backend(pp.env) repo = backend.get_cmis_repository() @@ -168,43 +169,54 @@ class AdefpatReunionGAP(models.Model): class AlfodooProject(models.Model): _inherit = 'project.project' - project_cmis_folder = fields.CmisFolder( + cmis_folder = fields.CmisFolder( allow_create=True, allow_delete=False, create_properties_get='_get_folder_properties', create_method='_create_folder', ) + task_cmis_folder = fields.CmisFolder( + allow_create=False, + allow_delete=False, + ) # ------------------------------------------------------ # Override Alfodoo # ------------------------------------------------------ def _get_folder_properties(self, records, backend): """ - Ajoute les propriétés au dossier lors de la création dans Alfresco + Ajoute les propriétés au dossier lors de la création dans Alfresco """ return { 'cmis:secondaryObjectTypeIds': [ + 'P:adefpat:departement', 'P:adefpat:dossier', - 'P:up:UploadFolder', + 'P:adefpat:typesListe', + 'P:cm:taggable', 'P:cm:titled', 'P:sys:cascadeUpdate', - 'P:adefpat:typesListe', - 'P:cm:taggable', 'P:sys:localized' + 'P:sys:localized', + 'P:up:UploadFolder' ], - 'up:allowedTypes': 'adefpat:content', + 'adefpat:cfd': str(self.user_id.name), + 'adefpat:departement': str( + self.departement) if self.departement else '', 'adefpat:dossierNom': str(self.name), 'adefpat:dossierNumero': str(self.num_dossier) if self.num_dossier else '', 'adefpat:financementConvention': str(self.type_convention_id.name), + 'up:allowedTypes': 'adefpat:content' } + def _create_folder(self, records, backend): """ Crée le répertoire Projets si il n'existe pas Crées l'architecture à mettre en place (PP, Gap, Consultants) + Met à jour le répertoire et les sous dossiers si ils existent :param records: project records :param backend: project backend - :return: project_cmis_folder objectId + :return: cmis_folder objectId """ # Get project folder project_cmis = self.env.user.company_id.project_cmis @@ -212,163 +224,110 @@ class AlfodooProject(models.Model): raise UserError( "Le répertoire Projet d'Alfresco n'est pas configuré") - # Check de si le répertoire existe for project in self: - # Path parent des projets - parent_path = backend.get_cmis_repository().getFolder( - project_cmis).getPaths() - # Path projet - path_proj = parent_path + [project.name] - path = '/'.join(path_proj) - project.project_cmis_folder = backend.get_folder_by_path(path) - project.project_cmis_folder.updateProperties( - project._get_folder_properties(records, backend)) - + if not project.cmis_folder: + # Path parent des projets + parent_path = backend.get_cmis_repository().getFolder( + project_cmis).getPaths() + # Path projet + path_proj = parent_path + [project.name] + path = '/'.join(path_proj) + # Création du dossier projet + project.cmis_folder = backend.get_folder_by_path(path) + # Actualisation de ses propriétés + project.cmis_folder.updateProperties( + project._get_folder_properties(records, backend)) + + # Création / Mise à jour de l'architecture + else: + # Path du dossier projet + path_proj = backend.get_cmis_repository().getFolder( + project.cmis_folder).getPaths() + + # Dossiers Niveau 0 (sans parent) archi_dossier = self.env['adefpat.archi.dossier'].search([ - ('parent_id', '=', False), ('specifique', '=', False)]) - + ('parent_id', '=', False), + ]) for dossier in archi_dossier: - path_niveau0 = path_proj + [dossier.name] - path = '/'.join(path_niveau0) - cmis_obj = backend.get_folder_by_path(path) + # Création du dossier N0 + path_n0 = path_proj + [dossier.name] + path = '/'.join(path_n0) + cmis_obj = backend.get_folder_by_path(path) # Mise à jour des listes de documents self.update_list_properties(dossier, cmis_obj) - if dossier.name == "comm": - cmis_obj.updateProperties( - { - 'cmis:secondaryObjectTypeIds': [ - 'P:adefpat:dossier', - 'P:adefpat:departement', - 'P:up:UploadFolder', - 'P:cm:titled', - 'P:sys:cascadeUpdate', - 'P:adefpat:typesListe', - 'P:cm:taggable', - 'P:sys:localized' - ], - 'up:allowedTypes': 'adefpat:content', - 'adefpat:departement': str(project.departement) if project.departement else '', - }) - # Création des enfants - child_folder = self.env['adefpat.archi.dossier'].search([ - ('parent_id', '=', dossier.id), ('specifique', '=', False)]) - for child in child_folder: - path_niveau1 = path_niveau0 + [child.name] - path = '/'.join(path_niveau1) - cmis_obj = backend.get_folder_by_path(path) - self.update_list_properties(child, cmis_obj) - - # Création des dossiers spécfiques - archi_spe = self.env['adefpat.archi.dossier'].search([ - ('parent_id', '=', dossier.id), ('specifique', '!=', False)]) - for child in archi_spe: - if child.name == 'nom_benef': - for pp in project.porteurs_projets_ids: - path_pp = path_niveau0 + [pp.porteur_id.name] - path = '/'.join(path_pp) - # Création de l'objet - pp.pp_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.pp_cmis_folder, pp, path_pp, backend, child) - if child.name == 'nom_CF': - for pp in project.consulant_ids: - path_pp = path_niveau0 + [pp.partner_id.name] - path = '/'.join(path_pp) - # Création de l'objet - pp.consult_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.consult_cmis_folder, pp, path_pp, backend, child) - - if child.name == 'date_gap': - for pp in project.reunion_ids: - path_pp = path_niveau0 + [str(pp.date)] - path = '/'.join(path_pp) - # Création de l'objet - pp.gap_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.gap_cmis_folder, pp, path_pp, backend, child) - + # Fonction récursive de création pour les enfants + if dossier.child_ids: + self.recursive_child( + project, dossier.child_ids, path_n0, cmis_obj, backend) + + # Stockage du dossier séance pour les tâches + path_seances = '/'.join(path_proj + ['seances']) + project.task_cmis_folder = backend.get_folder_by_path(path_seances) + def update_folder(self): """ Mets à jour les dossiers qui ne sont pas encore crés (PP, Gap, Consultants) :param records: project records :param backend: project backend - :return: project_cmis_folder objectId + :return: cmis_folder objectId """ for project in self: backend = self.env['cmis.backend'].sudo().search([]) - project_path = backend.get_cmis_repository().getFolder( - project.project_cmis_folder).getPaths() - - archi_spe = self.env['adefpat.archi.dossier'].search([ - ('parent_id', '!=', False), ('specifique', '!=', False)]) - for child in archi_spe: - path_parent = project_path + [child.parent_id.name] - if child.name == 'nom_benef': - for pp in project.porteurs_projets_ids: - if not pp.pp_cmis_folder: - path_pp = path_parent + [pp.porteur_id.name] - path = '/'.join(path_pp) - # Création de l'objet - pp.pp_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.pp_cmis_folder, pp, path_pp, backend, child) - if child.name == 'nom_CF': - for pp in project.consulant_ids: - if not pp.consult_cmis_folder: - path_pp = path_parent + [pp.partner_id.name] - path = '/'.join(path_pp) - # Création de l'objet - pp.consult_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.consult_cmis_folder, pp, path_pp, backend, child) - - if child.name == 'date_gap': - for pp in project.reunion_ids: - if not pp.gap_cmis_folder: - path_pp = path_parent + [str(pp.date)] - path = '/'.join(path_pp) - # Création de l'objet - pp.gap_cmis_folder = backend.get_folder_by_path(path) - self.create_child(pp.gap_cmis_folder, pp, path_pp, backend, child) - + project._create_folder(self, backend) + def update_list_properties(self, dossier, cmis_folder): # Récupération de tous les documents pour le dossier en entrée list_doc = self.env['adefpat.list.type.doc'].search([ - '&', '|', ('convention_ids', '=', False), - ('convention_ids', '=', self.type_convention_id.id), + '&', '|', ('convention_ids', '=', False), + ('convention_ids', '=', self.type_convention_id.id), ('dossier', '=', dossier.id)]) # Récupération des documents dont la complétude est cochée list_doc_completude = list_doc.filtered(lambda r: r.completude == True) - + doc = list_doc.mapped('name') doc_completude = list_doc_completude.mapped('name') - + + properties = self._get_folder_properties(self, cmis_folder) + if doc: - cmis_folder.updateProperties({ + properties.update({ 'adefpat:typesListe': doc, 'adefpat:typesListeCompletude': doc_completude, }) - - def create_child(self, object_cmis, object, path_object, backend, child): - # Mise à jour des propriétés du dossier - object_cmis.updateProperties(object._get_folder_properties()) - - # Mise à jour des documents attendus - self.update_list_properties(child, object_cmis) - - # Vérification si des dossiers enfants doivent être créés - child_folder_spe = self.env['adefpat.archi.dossier'].search([ - ('parent_id', '=', child.id), ('specifique', '!=', False)]) - - for child in child_folder_spe: - path_niveau1 = path_object + [child.name] - path = '/'.join(path_niveau1) - cmis_obj = backend.get_folder_by_path(path) - self.update_list_properties(child, cmis_obj) + cmis_folder.updateProperties(properties) + + def recursive_child(self, project, child_ids, path, cmis_obj, backend): + for child in child_ids: + if child.specifique: + object_ids = self.env[child.model_id.model].search([ + ('project_id', '=', project.id) + ]) + for obj in object_ids: + path_n = path + [obj.display_name] + path_o = '/'.join(path_n) + obj.cmis_folder = cmis_obj_n = backend.get_folder_by_path(path_o) + self.update_list_properties(child, cmis_obj_n) + cmis_obj_n.updateProperties(obj._get_folder_properties()) + if child.child_ids: + self.recursive_child( + child, child.child_ids, path_n, cmis_obj_n, + backend) + else: + path_n = path + [child.name] + path_o = '/'.join(path_n) + cmis_obj_n = backend.get_folder_by_path(path_o) + self.update_list_properties(child, cmis_obj_n) + if child.child_ids: + self.recursive_child( + child, child.child_ids, path_n, cmis_obj_n, backend) @api.multi def validate_ca(self): super(AlfodooProject, self).validate_ca() for project in self: - backend = self._fields['project_cmis_folder'] + backend = self._fields['cmis_folder'] properties = project._get_folder_properties( project, backend) properties.update({'adefpat:dossierNumero': project.num_dossier}) diff --git a/models/project_task.py b/models/project_task.py index e72c21fecce202b5b71ac14c0ec8a430f244a243..dcc66600b22a6c45328a55df35b49b1e254edfd8 100644 --- a/models/project_task.py +++ b/models/project_task.py @@ -8,22 +8,8 @@ from odoo.addons.cmis_field import fields class AlfodooProjectTask(models.Model): _inherit = 'project.task' - @api.model - def default_get(self, fields): - res = super(AlfodooProjectTask, self).default_get(fields) - if 'default_project_id' in self.env.context: - default_project_id = self.env['project.project'].browse(self.env.context['default_project_id']) - if default_project_id.exists().project_cmis_folder: - backend_name = default_project_id._fields['project_cmis_folder'] - backend = backend_name.get_backend(default_project_id.env) - path_parts = backend.initial_directory_write.split('/') - path_proj = path_parts + [default_project_id.name] + ['seances'] - path = '/'.join(path_proj) - res.update({'task_cmis_folder': backend.get_folder_by_path(path)}) - return res - - task_cmis_folder = fields.CmisFolder( + cmis_folder = fields.CmisFolder( allow_create=False, allow_delete=False, - create_properties_get='_get_folder_properties', + related='project_id.task_cmis_folder', ) diff --git a/views/project_views.xml b/views/project_views.xml index eb59b7102e7f4500b934533b54885336af774fba..5091b1e613f721c93d82c6500e07b362c54adb69 100644 --- a/views/project_views.xml +++ b/views/project_views.xml @@ -12,7 +12,10 @@ <field name="inherit_id" ref="adefpat_project.edit_project"/> <field name="arch" type="xml"> <header position="inside"> - <button string="Dossiers Complets ?" type="object" class="btn-secondary" name="get_pp_completion" attrs="{'invisible': [('porteurs_projets_ids', '=', False)]}"/> + <button string="Dossiers Complets ?" + type="object" class="btn-secondary" + name="get_pp_completion" + attrs="{'invisible': ['|', ('porteurs_projets_ids', '=', False), ('cmis_folder', '=', False)]}"/> </header> <!-- Ajoute l'onglet Documents dans la vue projet --> <xpath expr="//notebook" position="inside"> @@ -20,8 +23,8 @@ <group> <field name="liens_hypertextes"/> </group> - <button name="update_folder" string="Mettre à jour les dossiers" type="object" attrs="{'invisible': [('project_cmis_folder', '=', False)]}"/> - <field name="project_cmis_folder" + <button name="update_folder" string="Mettre à jour les dossiers" type="object" attrs="{'invisible': [('cmis_folder', '=', False)]}"/> + <field name="cmis_folder" canCreateFolder="0" canCreateDocument="0" canImportNewVersion="0" @@ -34,17 +37,17 @@ </page> </xpath> <xpath expr="//field[@name='porteurs_projets_ids']//tree//field[@name='eligible']" position="after"> - <field name="pp_cmis_folder" invisible="1"/> - <field name="pp_cmis_folder_completion" string="Complet ?" attrs="{'invisible': [('pp_cmis_folder', '=', False)]}"/> - <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('pp_cmis_folder', '=', False)]}"/> + <field name="cmis_folder" invisible="1"/> + <field name="cmis_folder_completion" string="Complet ?" attrs="{'invisible': [('cmis_folder', '=', False)]}"/> + <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('cmis_folder', '=', False)]}"/> </xpath> <xpath expr="//field[@name='consulant_ids']//tree//field[@name='is_selected']" position="after"> - <field name="consult_cmis_folder" invisible="1"/> - <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('consult_cmis_folder', '=', False)]}"/> + <field name="cmis_folder" invisible="1"/> + <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('cmis_folder', '=', False)]}"/> </xpath> <xpath expr="//field[@name='reunion_ids']//tree//field[@name='date']" position="after"> - <field name="gap_cmis_folder" invisible="1"/> - <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('gap_cmis_folder', '=', False)]}"/> + <field name="cmis_folder" invisible="1"/> + <button icon="/adefpat_alfodoo/static/src/img/alfresco-logo-16.png" name="get_content_details_url" string="voir" type="object" attrs="{'invisible': [('cmis_folder', '=', False)]}"/> </xpath> </field> </record>