Skip to content
Snippets Groups Projects
api_alfresco.py 9.88 KiB
Newer Older
  • Learn to ignore specific revisions
  • Benjamin's avatar
    Benjamin committed
    # © 2019 Le Filament (<http://www.le-filament.com>)
    # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
    
    import logging
    
    Benjamin's avatar
    Benjamin committed
    
    
    import requests
    from cmislib.exceptions import (
        ContentAlreadyExistsException,
        InvalidArgumentException,
        ObjectNotFoundException,
        UpdateConflictException,
    )
    
    from odoo import _, exceptions, models
    
    Benjamin's avatar
    Benjamin committed
    
    _logger = logging.getLogger(__name__)
    
    
    
    Benjamin's avatar
    Benjamin committed
    class CgscopAlfresco(models.AbstractModel):
    
        """Appelle l'API alfresco et implémente les fonctions suivantes :
    
    Benjamin's avatar
    Benjamin committed
    
        alfresco_list_docs : liste les documents
        """
    
    
        _name = "cgscop.alfresco"
        _description = "Connecteur Alfresco"
    
    Benjamin's avatar
    Benjamin committed
    
    
        def alfresco_get_by_url(self, url, call_type, json=None, files=None):
    
            """Création de la requête à Alfresco
    
    
    Benjamin's avatar
    Benjamin committed
            :param url: action API Alfresco
            :param call_type: post/get
            :param json: data to post
    
            :param files: byte to upload
            :param data: data to post
    
    Benjamin's avatar
    Benjamin committed
    
            @return response au format JSON
            """
            _logger.info("Calling %s" % url)
    
            param = self.env["cmis.backend"].sudo().search([["active", "=", True]])
    
                raise exceptions.UserError(
                    _("La connexion avec Alfresco n'est pas configurée !")
                )
    
            alfresco_url = param.url
            alfresco_ssl = param.ssl
    
            basicAuthCredentials = (param.username, param.password)
    
    Benjamin's avatar
    Benjamin committed
            try:
    
    Benjamin's avatar
    Benjamin committed
                    response = requests.get(
                        alfresco_url + url,
    
    Benjamin's avatar
    Benjamin committed
                    response = requests.post(
                        alfresco_url + url,
                        auth=basicAuthCredentials,
    
                        files=files,
                        verify=alfresco_ssl,
                        timeout=15,
                    )
                elif call_type == "put":
                    response = requests.put(
                        alfresco_url + url,
                        auth=basicAuthCredentials,
                        data=json,
                        files=files,
    
                    )
                elif call_type == "delete":
    
    Benjamin's avatar
    Benjamin committed
                    response = requests.delete(
                        alfresco_url + url,
                        auth=basicAuthCredentials,
    
    Benjamin's avatar
    Benjamin committed
            except Exception as err:
                _logger.warning(
                    "Erreur de connexion. URL: %s",
                    err.__str__(),
                )
    
                raise exceptions.ValidationError(err.__str__())
    
            # Gestion erreur API
            if response.status_code not in [200, 201]:
    
                    message = response.json().get("message")
                except Exception:
    
                raise exceptions.ValidationError(
                    _(
                        "L'appel url '%s' a échoué\n"
                        "- Code erreur : %d\n"
                        "- Message : %s" % (response.url, response.status_code, message)
                    )
                )
    
    Benjamin's avatar
    Benjamin committed
    
        # Get Methods
    
            """Liste les documents pour un organisme (raison sociale)
            :param name: raison sociale de la structure
    
    Benjamin's avatar
    Benjamin committed
            """
    
            url = "/alfresco/s/erp/listedocuments?nodeId=" + node_id
            return self.alfresco_get_by_url(url=url, call_type="get").json()
    
    Benjamin's avatar
    Benjamin committed
    
        def alfresco_list_type(self):
    
            """Liste le valeurs du formulaire de dépôt d'un nouveau document
    
    Benjamin's avatar
    Benjamin committed
    
            @return: dict des valeurs possibles pour période, validité, type
            """
    
            url = "/alfresco/s/api/properties?nsp=crm&n=document"
            list_type = self.alfresco_get_by_url(url=url, call_type="get").json()
    
    Benjamin's avatar
    Benjamin committed
            return {
    
                "periode": self.get_allowed_values(
                    list_type=list_type, value="crm:periode"
                ),
                "type": self.get_allowed_values(list_type=list_type, value="crm:type"),
    
    Benjamin's avatar
    Benjamin committed
            }
    
        def alfresco_get_doc(self, nodeRef):
    
            """Retourne le contenu d'un document en base64
            :param nodeRef: id Alfresco
    
    Benjamin's avatar
    Benjamin committed
            """
    
            url = "/alfresco/s/document/" + nodeRef
            return self.alfresco_get_by_url(url=url, call_type="get").json()
    
            """Liste les documents pour un organisme (raison sociale)
            :param username: username de l'utilisateur
    
            url = "/alfresco/s/authentifier-entantque?compte=" + username
            result = self.alfresco_get_by_url(url=url, call_type="get")
    
            tree = et.ElementTree(et.fromstring(result.content))
            root = tree.getroot()
            return root[0].text
    
    Benjamin's avatar
    Benjamin committed
    
        # Post Methods
        def alfresco_create_organism(self, partner):
    
            """Création d'un dossier Organisme
    
    Benjamin's avatar
    Benjamin committed
    
            :param partner: objet Odoo créé
    
            @return: id Alfresco (nodeRef) du dossier
            """
    
            url = "/alfresco/s/erp/createdossierorganisme"
    
    Benjamin's avatar
    Benjamin committed
            json = {
    
                "raisonSociale": partner.name,
    
    Benjamin's avatar
    Benjamin committed
                "id": partner.id,
                "siret": partner.siret,
    
    Benjamin - Le Filament's avatar
    Benjamin - Le Filament committed
                "numAdherent": partner.member_number,
    
    Benjamin's avatar
    Benjamin committed
            }
            return self.get_nodeRef(
    
                self.alfresco_get_by_url(url=url, call_type="post", json=json).json()
            )
    
    Benjamin's avatar
    Benjamin committed
    
    
            """Mise à jour d'un dossier Organisme
    
    
            :param partner: objet Odoo créé
    
            @return: id Alfresco (nodeRef) du dossier
            """
    
            url = "/alfresco/s/erp/updatedossierorganisme/" + partner.id_alfresco
    
                "raisonSociale": partner.name,
    
    Benjamin - Le Filament's avatar
    Benjamin - Le Filament committed
                "numAdherent": partner.member_number,
    
                self.alfresco_get_by_url(url=url, call_type="post", json=json).json()
            )
    
    Benjamin's avatar
    Benjamin committed
    
        # Delete Methods
        def alfresco_remove(self, nodeRef):
    
            """Supprime un document d'Alfresco
            :param id_doc: id du document Alfresco
    
    Benjamin's avatar
    Benjamin committed
            """
    
            url = "/alfresco/s/document/" + nodeRef
            return self.alfresco_get_by_url(url=url, call_type="delete").json()
    
    Benjamin's avatar
    Benjamin committed
    
        # Others
        def get_allowed_values(self, list_type, value):
    
            """Fonction qui itère dans l'objet retourné"""
            list_selected = list(filter(lambda i: i["name"] == value, list_type))
            return (
                list_selected[0]
                .get("constraints")[0]
                .get("parameters")[0]
                .get("allowedValues")
            )
    
    Benjamin's avatar
    Benjamin committed
    
        def get_nodeRef(self, result):
    
            """Renvoie la référence Alfresco d'un JSON contenant au premier
    
    Benjamin's avatar
    Benjamin committed
            niveau la clé "nodeRef" puis supprime le chemin du workspace
            """
    
            return result.get("nodeRef", "").replace("workspace://SpacesStore/", "")
    
        def push_alfresco_file(self, file, name, metadata=None, backend=None, folder=None):
    
            Ajoute un fichier sur la GED Alfresco
            @return: fonction get_partner_files() de res.partner
    
                backend = self.env["cmis.backend"].search([], limit=1)
    
            if not folder:
                raise exceptions.ValidationError(
    
                    _("Le dossier parent n'existe pas ou n'est pas renseigné !")
                )
    
            cmis_rep = backend.get_cmis_repository()
            cmis_obj = cmis_rep.getObject(folder)
    
            _logger.info("Chargement document Alfresco : %s" % name)
    
    jordan's avatar
    jordan committed
            try:
    
                file_upload = cmis_obj.createDocument(
                    name=name,
    
                    contentFile=file,
    
                    contentType="application/pdf",
    
    jordan's avatar
    jordan committed
                return file_upload
    
            except UpdateConflictException:
                _logger.info("Le document %s existe déjà dans le dossier spécifié" % name)
                # Recherche noderef document existant
                children = cmis_obj.getChildren().getResults()
                old_cmis_file = list(filter(lambda f: f.name == name, children))[0]
                # Création d'une copie de travail du document pour versionnage
                pwc = old_cmis_file.checkout()
                # Mise à jour de la version
                pwc.checkin(
                    contentFile=file, contentType="application/pdf", properties=metadata
                )
    
            except (
                ContentAlreadyExistsException,
                ObjectNotFoundException,
                InvalidArgumentException,
            ) as e:
    
                _logger.error(e)
    
    jordan's avatar
    jordan committed
                raise exceptions.ValidationError(
    
                    _(
                        "L'appel à Alfresco à échoué :\n- Code: %s\n\n- Url\n%s\n\n- Détail\n%s"
                    )
    
                    % (e.status, e.url, e.details)
    
            except Exception as e:
                raise exceptions.ValidationError(e)
    
    
        def push_alfresco_file_api(self, file, name, metadata=None, folder=None):
            """
            Ajoute un fichier sur la GED Alfresco
            @return: fonction get_partner_files() de res.partner
            """
            if not folder:
                raise exceptions.ValidationError(
                    _("Le dossier parent n'existe pas ou n'est pas renseigné !")
                )
    
            # url = "/nodes/%s/children" % folder
            url = (
                "/alfresco/api/-default-/public/alfresco/versions/1/nodes/%s/children?majorVersion=true"
                % folder
            )
            _logger.info("Chargement document Alfresco : %s" % name)
    
            content_type = "multipart/form-data"
    
            params = {
                "name": name,
                "nodeType": "cmis:document",
                "overwrite": True,
                "properties": metadata,
            }
            files = {"filedata": (name, file, content_type, params)}
            return self.alfresco_get_by_url(url=url, call_type="post", files=files).json()