From 325ab9a6113a86dd576942baf7cf9ef5008e544d Mon Sep 17 00:00:00 2001
From: Julien - Le Filament <julien@le-filament.com>
Date: Wed, 16 Apr 2025 11:00:41 +0200
Subject: [PATCH] [UPD] pre commit

---
 .gitignore                                    |  89 ++++++++
 .pre-commit-config.yaml                       | 123 +++++++++++
 .pylintrc                                     | 123 +++++++++++
 .pylintrc-mandatory                           |  98 +++++++++
 .ruff.toml                                    |  30 +++
 README.rst                                    |  52 ++---
 __init__.py                                   |  10 +-
 __manifest__.py                               |  38 ++--
 eslint.config.cjs                             | 202 ++++++++++++++++++
 models/__init__.py                            |   6 +-
 .../sharepoint_mixin.cpython-312.pyc          | Bin 7100 -> 7097 bytes
 models/res_config_settings.py                 |   8 +-
 models/res_partner.py                         |  17 +-
 models/sharepoint_mixin.py                    |  44 ++--
 prettier.config.cjs                           |  14 ++
 security/ir.model.access.csv                  |   4 +-
 views/res_config_settings.xml                 |  64 +++---
 views/res_partner_views.xml                   |  48 ++---
 18 files changed, 832 insertions(+), 138 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 .pre-commit-config.yaml
 create mode 100644 .pylintrc
 create mode 100644 .pylintrc-mandatory
 create mode 100644 .ruff.toml
 create mode 100644 eslint.config.cjs
 create mode 100644 prettier.config.cjs

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..109270f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,89 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+/.venv
+/.pytest_cache
+/.ruff_cache
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+bin/
+build/
+develop-eggs/
+dist/
+eggs/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+*.eggs
+.copier-answers.yml
+
+# Windows installers
+*.msi
+
+# Debian packages
+*.deb
+
+# Redhat packages
+*.rpm
+
+# MacOS packages
+*.dmg
+*.pkg
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+
+# Pycharm
+.idea
+
+# Eclipse
+.settings
+
+# Visual Studio cache/options directory
+.vs/
+.vscode
+
+# OSX Files
+.DS_Store
+
+# Django stuff:
+*.log
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# Rope
+.ropeproject
+
+# Sphinx documentation
+docs/_build/
+
+# Backup files
+*~
+*.swp
+
+# OCA rules
+!static/lib/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..207e4c9
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,123 @@
+exclude: |
+  (?x)
+  # NOT INSTALLABLE ADDONS
+  # END NOT INSTALLABLE ADDONS
+  # Files and folders generated by bots, to avoid loops
+  ^setup/|/static/description/index\.html$|
+  # We don't want to mess with tool-generated files
+  .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|^eslint.config.cjs|^prettier.config.cjs|
+  # Maybe reactivate this when all README files include prettier ignore tags?
+  ^README\.md$|
+  # Library files can have extraneous formatting (even minimized)
+  /static/(src/)?lib/|
+  # Repos using Sphinx to generate docs don't need prettying
+  ^docs/_templates/.*\.html$|
+  # Don't bother non-technical authors with formatting issues in docs
+  readme/.*\.(rst|md)$|
+  # Ignore build and dist directories in addons
+  /build/|/dist/|
+  # Ignore test files in addons
+  /tests/samples/.*|
+  # You don't usually want a bot to modify your legal texts
+  (LICENSE.*|COPYING.*)
+default_language_version:
+  python: python3
+  node: "22.9.0"
+repos:
+  - repo: local
+    hooks:
+      # These files are most likely copier diff rejection junks; if found,
+      # review them manually, fix the problem (if needed) and remove them
+      - id: forbidden-files
+        name: forbidden files
+        entry: found forbidden files; remove them
+        language: fail
+        files: "\\.rej$"
+      - id: en-po-files
+        name: en.po files cannot exist
+        entry: found a en.po file
+        language: fail
+        files: '[a-zA-Z0-9_]*/i18n/en\.po$'
+  - repo: https://github.com/oca/maintainer-tools
+    rev: bf9ecb9938b6a5deca0ff3d870fbd3f33341fded
+    hooks:
+      # update the NOT INSTALLABLE ADDONS section above
+      - id: oca-update-pre-commit-excluded-addons
+      - id: oca-fix-manifest-website
+        args: ["https://le-filament.com"]
+  - repo: https://github.com/OCA/odoo-pre-commit-hooks
+    rev: v0.0.33
+    hooks:
+      - id: oca-checks-odoo-module
+      - id: oca-checks-po
+        args:
+          - --disable=po-pretty-format
+  - repo: local
+    hooks:
+      - id: prettier
+        name: prettier (with plugin-xml)
+        entry: prettier
+        args:
+          - --write
+          - --list-different
+          - --ignore-unknown
+        types: [text]
+        files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$
+        language: node
+        additional_dependencies:
+          - "prettier@3.3.3"
+          - "@prettier/plugin-xml@3.4.1"
+  - repo: local
+    hooks:
+      - id: eslint
+        name: eslint
+        entry: eslint
+        args:
+          - --color
+          - --fix
+        verbose: true
+        types: [javascript]
+        language: node
+        additional_dependencies:
+          - "eslint@9.12.0"
+          - "eslint-plugin-jsdoc@50.3.1"
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.6.0
+    hooks:
+      - id: trailing-whitespace
+        # exclude autogenerated files
+        exclude: /README\.rst$|\.pot?$
+      - id: end-of-file-fixer
+        # exclude autogenerated files
+        exclude: /README\.rst$|\.pot?$
+      - id: debug-statements
+      - id: fix-encoding-pragma
+        args: ["--remove"]
+      - id: check-case-conflict
+      - id: check-docstring-first
+      - id: check-executables-have-shebangs
+      - id: check-merge-conflict
+        # exclude files where underlines are not distinguishable from merge conflicts
+        exclude: /README\.rst$|^docs/.*\.rst$
+      - id: check-symlinks
+      - id: check-xml
+      - id: mixed-line-ending
+        args: ["--fix=lf"]
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: v0.6.8
+    hooks:
+      - id: ruff
+        args: [--fix, --exit-non-zero-on-fix]
+      - id: ruff-format
+  - repo: https://github.com/OCA/pylint-odoo
+    rev: v9.1.3
+    hooks:
+      - id: pylint_odoo
+        name: pylint with optional checks
+        args:
+          - --rcfile=.pylintrc
+          - --exit-zero
+        verbose: true
+      - id: pylint_odoo
+        args:
+          - --rcfile=.pylintrc-mandatory
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..b855a92
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,123 @@
+
+
+[MASTER]
+load-plugins=pylint_odoo
+score=n
+
+[ODOOLINT]
+readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
+manifest-required-authors=Le Filament
+manifest-required-keys=license
+manifest-deprecated-keys=description,active
+license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3
+valid-odoo-versions=18.0
+
+[MESSAGES CONTROL]
+disable=all
+
+# This .pylintrc contains optional AND mandatory checks and is meant to be
+# loaded in an IDE to have it check everything, in the hope this will make
+# optional checks more visible to contributors who otherwise never look at a
+# green travis to see optional checks that failed.
+# .pylintrc-mandatory containing only mandatory checks is used the pre-commit
+# config as a blocking check.
+
+enable=anomalous-backslash-in-string,
+    api-one-deprecated,
+    api-one-multi-together,
+    assignment-from-none,
+    attribute-deprecated,
+    class-camelcase,
+    dangerous-default-value,
+    dangerous-view-replace-wo-priority,
+    development-status-allowed,
+    duplicate-id-csv,
+    duplicate-key,
+    duplicate-xml-fields,
+    duplicate-xml-record-id,
+    eval-referenced,
+    eval-used,
+    incoherent-interpreter-exec-perm,
+    license-allowed,
+    manifest-author-string,
+    manifest-deprecated-key,
+    manifest-required-author,
+    manifest-required-key,
+    manifest-version-format,
+    method-compute,
+    method-inverse,
+    method-required-super,
+    method-search,
+    openerp-exception-warning,
+    pointless-statement,
+    pointless-string-statement,
+    print-used,
+    redundant-keyword-arg,
+    redundant-modulename-xml,
+    reimported,
+    relative-import,
+    return-in-init,
+    rst-syntax-error,
+    sql-injection,
+    too-few-format-args,
+    translation-field,
+    translation-required,
+    unreachable,
+    use-vim-comment,
+    wrong-tabs-instead-of-spaces,
+    xml-syntax-error,
+    attribute-string-redundant,
+    character-not-valid-in-resource-link,
+    consider-merging-classes-inherited,
+    context-overridden,
+    create-user-wo-reset-password,
+    dangerous-filter-wo-user,
+    dangerous-qweb-replace-wo-priority,
+    deprecated-data-xml-node,
+    deprecated-openerp-xml-node,
+    duplicate-po-message-definition,
+    except-pass,
+    file-not-used,
+    invalid-commit,
+    manifest-maintainers-list,
+    missing-newline-extrafiles,
+    missing-readme,
+    missing-return,
+    odoo-addons-relative-import,
+    old-api7-method-defined,
+    po-msgstr-variables,
+    po-syntax-error,
+    renamed-field-parameter,
+    resource-not-exist,
+    str-format-used,
+    test-folder-imported,
+    translation-contains-variable,
+    translation-positional-used,
+    unnecessary-utf8-coding-comment,
+    website-manifest-key-not-valid-uri,
+    xml-attribute-translatable,
+    xml-deprecated-qweb-directive,
+    xml-deprecated-tree-attribute,
+    external-request-timeout,
+    # messages that do not cause the lint step to fail
+    consider-merging-classes-inherited,
+    create-user-wo-reset-password,
+    dangerous-filter-wo-user,
+    deprecated-module,
+    file-not-used,
+    invalid-commit,
+    missing-manifest-dependency,
+    missing-newline-extrafiles,
+    missing-readme,
+    no-utf8-coding-comment,
+    odoo-addons-relative-import,
+    old-api7-method-defined,
+    redefined-builtin,
+    too-complex,
+    unnecessary-utf8-coding-comment
+
+
+[REPORTS]
+msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
+output-format=colorized
+reports=no
diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory
new file mode 100644
index 0000000..f945051
--- /dev/null
+++ b/.pylintrc-mandatory
@@ -0,0 +1,98 @@
+
+[MASTER]
+load-plugins=pylint_odoo
+score=n
+
+[ODOOLINT]
+readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
+manifest-required-authors=Le Filament
+manifest-required-keys=license
+manifest-deprecated-keys=description,active
+license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3
+valid-odoo-versions=18.0
+
+[MESSAGES CONTROL]
+disable=all
+
+enable=anomalous-backslash-in-string,
+    api-one-deprecated,
+    api-one-multi-together,
+    assignment-from-none,
+    attribute-deprecated,
+    class-camelcase,
+    dangerous-default-value,
+    dangerous-view-replace-wo-priority,
+    development-status-allowed,
+    duplicate-id-csv,
+    duplicate-key,
+    duplicate-xml-fields,
+    duplicate-xml-record-id,
+    eval-referenced,
+    eval-used,
+    incoherent-interpreter-exec-perm,
+    license-allowed,
+    manifest-author-string,
+    manifest-deprecated-key,
+    manifest-required-author,
+    manifest-required-key,
+    manifest-version-format,
+    method-compute,
+    method-inverse,
+    method-required-super,
+    method-search,
+    openerp-exception-warning,
+    pointless-statement,
+    pointless-string-statement,
+    print-used,
+    redundant-keyword-arg,
+    redundant-modulename-xml,
+    reimported,
+    relative-import,
+    return-in-init,
+    rst-syntax-error,
+    sql-injection,
+    too-few-format-args,
+    translation-field,
+    translation-required,
+    unreachable,
+    use-vim-comment,
+    wrong-tabs-instead-of-spaces,
+    xml-syntax-error,
+    attribute-string-redundant,
+    character-not-valid-in-resource-link,
+    consider-merging-classes-inherited,
+    context-overridden,
+    create-user-wo-reset-password,
+    dangerous-filter-wo-user,
+    dangerous-qweb-replace-wo-priority,
+    deprecated-data-xml-node,
+    deprecated-openerp-xml-node,
+    duplicate-po-message-definition,
+    except-pass,
+    file-not-used,
+    invalid-commit,
+    manifest-maintainers-list,
+    missing-newline-extrafiles,
+    missing-readme,
+    missing-return,
+    odoo-addons-relative-import,
+    old-api7-method-defined,
+    po-msgstr-variables,
+    po-syntax-error,
+    renamed-field-parameter,
+    resource-not-exist,
+    str-format-used,
+    test-folder-imported,
+    translation-contains-variable,
+    translation-positional-used,
+    unnecessary-utf8-coding-comment,
+    website-manifest-key-not-valid-uri,
+    xml-attribute-translatable,
+    xml-deprecated-qweb-directive,
+    xml-deprecated-tree-attribute,
+    external-request-timeout
+
+[REPORTS]
+msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
+output-format=colorized
+reports=no
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 0000000..0f1e35f
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,30 @@
+
+target-version = "py310"
+fix = true
+
+[lint]
+extend-select = [
+    "B",
+    "C90",
+    "E501",  # line too long (default 88)
+    "I",  # isort
+    "UP",  # pyupgrade
+]
+exclude = ["setup/*"]
+
+[format]
+exclude = ["setup/*"]
+
+[lint.per-file-ignores]
+"__init__.py" = ["F401", "I001"]  # ignore unused and unsorted imports in __init__.py
+"__manifest__.py" = ["B018"]  # useless expression
+
+[lint.isort]
+section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"]
+
+[lint.isort.sections]
+"odoo" = ["odoo"]
+"odoo-addons" = ["odoo.addons"]
+
+[lint.mccabe]
+max-complexity = 16
diff --git a/README.rst b/README.rst
index b304a63..ea18b8f 100644
--- a/README.rst
+++ b/README.rst
@@ -1,26 +1,26 @@
-.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
-   :target: http://www.gnu.org/licenses/agpl
-   :alt: License: AGPL-3
-
-
-=========================
-CG SCOP - SIOF sharepoint
-=========================
-
-Ce module permet de creer un repo sharepoint pour toute scop
-
-
-Credits
-=======
-
-Funders
--------
-
-The development of this module has been financially supported by:
-
-    Confédération Générale des SCOP (https://www.les-scop.coop)
-
-
-Contributors
-------------
-* Benjamin <benjamin@le-filament.com>
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/agpl
+   :alt: License: AGPL-3
+
+
+=========================
+CG SCOP - SIOF sharepoint
+=========================
+
+Ce module permet de creer un repo sharepoint pour toute scop
+
+
+Credits
+=======
+
+Funders
+-------
+
+The development of this module has been financially supported by:
+
+    Confédération Générale des SCOP (https://www.les-scop.coop)
+
+
+Contributors
+------------
+* Benjamin <benjamin@le-filament.com>
diff --git a/__init__.py b/__init__.py
index 7fc870d..48e1758 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,5 +1,5 @@
-# © 2020 Le Filament (<https://www.le-filament.com>)
-# © 2020 Confédération Générale des Scop (<https://www.les-scop.coop>)
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-
-from . import models
+# © 2020 Le Filament (<https://www.le-filament.com>)
+# © 2020 Confédération Générale des Scop (<https://www.les-scop.coop>)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from . import models
diff --git a/__manifest__.py b/__manifest__.py
index 9aa08a8..b86431d 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -1,19 +1,19 @@
-# © 2024 Le Filament (<https://www.le-filament.com>)
-# © 2024 Confédération Générale des Scop (<https://www.les-scop.coop>)
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-{
-    "name": "CG SCOP - Utilisation de SharepointAPI MsGraph",
-    "summary": "SIOF Sharepoint",
-    "author": "Le Filament, Confédération Générale des Scop",
-    "version": "18.0.1.0.0",
-    "license": "AGPL-3",
-    "depends": [],
-    "data": [
-        # security
-        # "security/ir.model.access.csv",
-        # views
-        "views/res_partner_views.xml",
-        "views/res_config_settings.xml"
-    ],
-    "external_dependencies": {"python": ["msal"]},
-}
+# © 2024 Le Filament (<https://www.le-filament.com>)
+# © 2024 Confédération Générale des Scop (<https://www.les-scop.coop>)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+{
+    "name": "CG SCOP - Utilisation de SharepointAPI MsGraph",
+    "summary": "SIOF Sharepoint",
+    "author": "Le Filament, Confédération Générale des Scop",
+    "version": "18.0.1.0.0",
+    "license": "AGPL-3",
+    "depends": [],
+    "data": [
+        # security
+        # "security/ir.model.access.csv",
+        # views
+        "views/res_partner_views.xml",
+        "views/res_config_settings.xml",
+    ],
+    "external_dependencies": {"python": ["msal"]},
+}
diff --git a/eslint.config.cjs b/eslint.config.cjs
new file mode 100644
index 0000000..0d5731f
--- /dev/null
+++ b/eslint.config.cjs
@@ -0,0 +1,202 @@
+jsdoc = require("eslint-plugin-jsdoc");
+
+const config = [{
+    plugins: {
+      jsdoc,
+    },
+
+    languageOptions: {
+        globals: {
+            _: "readonly",
+            $: "readonly",
+            fuzzy: "readonly",
+            jQuery: "readonly",
+            moment: "readonly",
+            odoo: "readonly",
+            openerp: "readonly",
+            owl: "readonly",
+            luxon: "readonly",
+        },
+
+        ecmaVersion: 2024,
+        sourceType: "script",
+    },
+
+    rules: {
+        "accessor-pairs": "warn",
+        "array-callback-return": "warn",
+        "callback-return": "warn",
+        "capitalized-comments": ["warn", "always", {
+            ignoreConsecutiveComments: true,
+            ignoreInlineComments: true,
+        }],
+        complexity: ["warn", 15],
+        "constructor-super": "warn",
+        "dot-notation": "warn",
+        eqeqeq: "warn",
+        "global-require": "warn",
+        "handle-callback-err": "warn",
+        "id-blacklist": "warn",
+        "id-match": "warn",
+        "init-declarations": "error",
+        "max-depth": "warn",
+        "max-nested-callbacks": "warn",
+        "max-statements-per-line": "warn",
+        "no-alert": "warn",
+        "no-array-constructor": "warn",
+        "no-caller": "warn",
+        "no-case-declarations": "warn",
+        "no-class-assign": "warn",
+        "no-cond-assign": "error",
+        "no-const-assign": "error",
+        "no-constant-condition": "warn",
+        "no-control-regex": "warn",
+        "no-debugger": "error",
+        "no-delete-var": "warn",
+        "no-div-regex": "warn",
+        "no-dupe-args": "error",
+        "no-dupe-class-members": "error",
+        "no-dupe-keys": "error",
+        "no-duplicate-case": "error",
+        "no-duplicate-imports": "error",
+        "no-else-return": "warn",
+        "no-empty-character-class": "warn",
+        "no-empty-function": "error",
+        "no-empty-pattern": "error",
+        "no-empty": "warn",
+        "no-eq-null": "error",
+        "no-eval": "error",
+        "no-ex-assign": "error",
+        "no-extend-native": "warn",
+        "no-extra-bind": "warn",
+        "no-extra-boolean-cast": "warn",
+        "no-extra-label": "warn",
+        "no-fallthrough": "warn",
+        "no-func-assign": "error",
+        "no-global-assign": "error",
+        "no-implicit-coercion": ["warn", {
+            allow: ["~"],
+        }],
+        "no-implicit-globals": "warn",
+        "no-implied-eval": "warn",
+        "no-inline-comments": "warn",
+        "no-inner-declarations": "warn",
+        "no-invalid-regexp": "warn",
+        "no-irregular-whitespace": "warn",
+        "no-iterator": "warn",
+        "no-label-var": "warn",
+        "no-labels": "warn",
+        "no-lone-blocks": "warn",
+        "no-lonely-if": "error",
+        "no-mixed-requires": "error",
+        "no-multi-str": "warn",
+        "no-native-reassign": "error",
+        "no-negated-condition": "warn",
+        "no-negated-in-lhs": "error",
+        "no-new-func": "warn",
+        "no-new-object": "warn",
+        "no-new-require": "warn",
+        "no-new-symbol": "warn",
+        "no-new-wrappers": "warn",
+        "no-new": "warn",
+        "no-obj-calls": "warn",
+        "no-octal-escape": "warn",
+        "no-octal": "warn",
+        "no-param-reassign": "warn",
+        "no-path-concat": "warn",
+        "no-process-env": "warn",
+        "no-process-exit": "warn",
+        "no-proto": "warn",
+        "no-prototype-builtins": "warn",
+        "no-redeclare": "warn",
+        "no-regex-spaces": "warn",
+        "no-restricted-globals": "warn",
+        "no-restricted-imports": "warn",
+        "no-restricted-modules": "warn",
+        "no-restricted-syntax": "warn",
+        "no-return-assign": "error",
+        "no-script-url": "warn",
+        "no-self-assign": "warn",
+        "no-self-compare": "warn",
+        "no-sequences": "warn",
+        "no-shadow-restricted-names": "warn",
+        "no-shadow": "warn",
+        "no-sparse-arrays": "warn",
+        "no-sync": "warn",
+        "no-this-before-super": "warn",
+        "no-throw-literal": "warn",
+        "no-undef-init": "warn",
+        "no-undef": "error",
+        "no-unmodified-loop-condition": "warn",
+        "no-unneeded-ternary": "error",
+        "no-unreachable": "error",
+        "no-unsafe-finally": "error",
+        "no-unused-expressions": "error",
+        "no-unused-labels": "error",
+        "no-unused-vars": "error",
+        "no-use-before-define": "error",
+        "no-useless-call": "warn",
+        "no-useless-computed-key": "warn",
+        "no-useless-concat": "warn",
+        "no-useless-constructor": "warn",
+        "no-useless-escape": "warn",
+        "no-useless-rename": "warn",
+        "no-void": "warn",
+        "no-with": "warn",
+        "operator-assignment": ["error", "always"],
+        "prefer-const": "warn",
+        radix: "warn",
+        "require-yield": "warn",
+        "sort-imports": "warn",
+        "spaced-comment": ["error", "always"],
+        strict: ["error", "function"],
+        "use-isnan": "error",
+
+        "jsdoc/check-tag-names": "warn",
+        "jsdoc/check-types": "warn",
+        "jsdoc/require-param-description": "off",
+        "jsdoc/require-return": "off",
+        "jsdoc/require-return-description": "off",
+        "jsdoc/require-return-type": "off",
+
+        "valid-typeof": "warn",
+        yoda: "warn",
+    },
+
+    settings: {
+        jsdoc: {
+            tagNamePreference: {
+                arg: "param",
+                argument: "param",
+                augments: "extends",
+                constructor: "class",
+                exception: "throws",
+                func: "function",
+                method: "function",
+                prop: "property",
+                return: "returns",
+                virtual: "abstract",
+                yield: "yields",
+            },
+            preferredTypes: {
+                array: "Array",
+                bool: "Boolean",
+                boolean: "Boolean",
+                number: "Number",
+                object: "Object",
+                str: "String",
+                string: "String",
+            },
+        },
+    },
+
+}, {
+    files: ["**/*.esm.js"],
+
+    languageOptions: {
+        ecmaVersion: 2024,
+        sourceType: "module",
+    },
+}];
+
+module.exports = config
diff --git a/models/__init__.py b/models/__init__.py
index 92f600f..5d2d0b3 100644
--- a/models/__init__.py
+++ b/models/__init__.py
@@ -1,3 +1,3 @@
-from . import sharepoint_mixin
-from . import res_partner
-from . import res_config_settings
+from . import sharepoint_mixin
+from . import res_partner
+from . import res_config_settings
diff --git a/models/__pycache__/sharepoint_mixin.cpython-312.pyc b/models/__pycache__/sharepoint_mixin.cpython-312.pyc
index a627ff0730f249ce3a35237fefc3a17ad1a7feae..76d4b69e91487e5daf71b94db78b0edde625abc3 100644
GIT binary patch
delta 132
zcmdmEzSErdG%qg~0|NttQR35dhmE|Zyo@T7xfo?Q^iopO5=(PRHfQjzVUks2WMF7u
z_`t&;YPrYqqKHce=M6#g3j!7$tPiB*HX93kW@1d*tS-EViLqew6H!rS#=6bFBsMUz
ks<QHb3YffJ>YI2yBcsrSwCiG87sa%`GJtqR+6)W~00R^!O8@`>

delta 135
zcmdmKzQ>&RG%qg~0|NuY!-S{lwHtX&c^OqFb1}+rh8Cw5=>?@Grfg2<UBe`=!N|bS
z!0>^GLDX`O<wX&f4$cRH78e98J6J!kF-XgAHW2vC#F(;KMR*SrW6|b^qN2=<4V%A9
nY+z(nXXXDCGI@>EH*rTMMxhC5*Tu9hifMgi0P%{n85kG<yagy0

diff --git a/models/res_config_settings.py b/models/res_config_settings.py
index 9e99b02..564800e 100644
--- a/models/res_config_settings.py
+++ b/models/res_config_settings.py
@@ -1,6 +1,5 @@
 # Copyright 2021- Le Filament (https://le-filament.com)
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
-from datetime import datetime
 
 from odoo import fields, models
 
@@ -28,7 +27,8 @@ class ResConfig(models.TransientModel):
             "siof_sharepoint.admin_sharepoint_secret_id", default=""
         )
         res.update(
-            admin_sharepoint_user_id=admin_sharepoint_user_id, admin_sharepoint_secret_id=admin_sharepoint_secret_id
+            admin_sharepoint_user_id=admin_sharepoint_user_id,
+            admin_sharepoint_secret_id=admin_sharepoint_secret_id,
         )
         return res
 
@@ -38,10 +38,12 @@ class ResConfig(models.TransientModel):
         )
 
         self.env["ir.config_parameter"].set_param(
-            "siof_sharepoint.admin_sharepoint_secret_id", self.admin_sharepoint_secret_id
+            "siof_sharepoint.admin_sharepoint_secret_id",
+            self.admin_sharepoint_secret_id,
         )
 
         return super().set_values()
+
     # ------------------------------------------------------
     # Computed fields / Search Fields
     # ------------------------------------------------------
diff --git a/models/res_partner.py b/models/res_partner.py
index a84fd76..c825719 100644
--- a/models/res_partner.py
+++ b/models/res_partner.py
@@ -11,30 +11,27 @@ class ResPartner(models.Model):
 
     @api.model_create_multi
     def create(self, vals_list):
-
         partners = super().create(vals_list)
         for partner in partners:
             partner.init_sharepoint_directory()
         return partners
 
     def action_redirect_to_sharepoint(self):
-
         # Action de redirection
         return {
-            'type': 'ir.actions.act_url',
-            'url': self.sharepoint_folder_url,
-            'target': 'new',
+            "type": "ir.actions.act_url",
+            "url": self.sharepoint_folder_url,
+            "target": "new",
         }
 
     def action_init_sharepoint(self):
-
-        if not self.sharepoint_folder_id: # and if self is a cooperative
+        if not self.sharepoint_folder_id:  # and if self is a cooperative
             # le dossier associé n est pas créé lets go
             self.init_sharepoint_directory()
 
         # Action de redirection
         return {
-            'type': 'ir.actions.act_url',
-            'url': self.sharepoint_folder_url,
-            'target': 'new',
+            "type": "ir.actions.act_url",
+            "url": self.sharepoint_folder_url,
+            "target": "new",
         }
diff --git a/models/sharepoint_mixin.py b/models/sharepoint_mixin.py
index 6001f48..91d6eb9 100644
--- a/models/sharepoint_mixin.py
+++ b/models/sharepoint_mixin.py
@@ -1,23 +1,26 @@
-from odoo import fields, models
-from odoo.exceptions import UserError
+import logging
 
 import requests
 from msal import ConfidentialClientApplication
 
-import logging
+from odoo import _, fields, models
+from odoo.exceptions import UserError
 
 _logger = logging.getLogger(__name__)
 ms_graph_site_url = "https://graph.microsoft.com/v1.0/sites"
 
 root_site = "doc-erp"
 tenant_id = "76d9117c-fdf5-4dff-9dd2-11a06fa7cd7e"
+default_timeout = 1
 
 
 class SharepointMixin(models.AbstractModel):
     _name = "sharepoint.mixin"
     _description = "Mixing to create scop drive in sharepoint"
 
-    sharepoint_folder_id = fields.Char("Identifiant di dossier dans sharepoint", default=None)
+    sharepoint_folder_id = fields.Char(
+        "Identifiant di dossier dans sharepoint", default=None
+    )
     sharepoint_folder_url = fields.Char(
         "Url sharepoint", default="https://cgscop.sharepoint.com/sites/doc-erp/SIOF"
     )
@@ -25,7 +28,10 @@ class SharepointMixin(models.AbstractModel):
     def create_folder(self, site_id, drive_id, folder_name, parent_path=None):
         # Vérifie si on crée un dossier à la racine ou dans un sous-dossier
         if parent_path:
-            url = f"{ms_graph_site_url}/{site_id}/drives/{drive_id}/root:/{parent_path}/{folder_name}"
+            url = (
+                f"{ms_graph_site_url}/{site_id}/drives/{drive_id}"
+                f"/root:/{parent_path}/{folder_name}"
+            )
         else:
             url = f"{ms_graph_site_url}/{site_id}/drives/{drive_id}/root/children"
 
@@ -36,14 +42,17 @@ class SharepointMixin(models.AbstractModel):
         }
 
         response = requests.post(
-            url, headers=self.make_request_headers(self.env.user), json=data
+            url,
+            headers=self.make_request_headers(self.env.user),
+            json=data,
+            timeout=default_timeout,
         )
 
         if response.status_code == 201:
             self.sharepoint_folder_id = response.json().get("id")
             self.sharepoint_folder_url = response.json().get("webUrl")
         else:
-            print(f"❌ Erreur ({response.status_code}):", response.text)
+            _logger.error(f"Erreur ({response.status_code}):", response.text)
             return None
 
     def init_sharepoint_directory(self):
@@ -73,7 +82,7 @@ class SharepointMixin(models.AbstractModel):
         )
 
         if not root_admin_user or not root_admin_pass:
-            raise UserError("Sharepoint admin credentials not configured")
+            raise UserError(_("Sharepoint admin credentials not configured"))
 
         app = ConfidentialClientApplication(
             root_admin_user, authority=authority, client_credential=root_admin_pass
@@ -89,12 +98,13 @@ class SharepointMixin(models.AbstractModel):
                     "Error acquiring authorization token. "
                     "Check your tenantID, clientID and clientSecret."
                 )
-                raise UserError(f"{accesstoken.get("error")}\n{accesstoken.get("error_description")}")
+                raise UserError(
+                    f"{accesstoken.get("error")}\n{accesstoken.get("error_description")}"
+                )
         else:
             _logger.info("Token retreived from MSAL Cache....")
         return
 
-
     def make_request_headers(self, connected_user):
         provider_id = connected_user.sudo().oauth_provider_id
 
@@ -105,7 +115,7 @@ class SharepointMixin(models.AbstractModel):
             token = self.get_ms_graph_admin_token()
 
         return {
-            "Authorization": f"Bearer " + token,
+            "Authorization": "Bearer " + token,
             "Content-type": "application/json",
         }
 
@@ -115,7 +125,11 @@ class SharepointMixin(models.AbstractModel):
         """
         try:
             url = f"{ms_graph_site_url}/root:/sites/doc-erp"
-            results = requests.get(url, headers=self.make_request_headers(self.env.user)).json()
+            results = requests.get(
+                url,
+                headers=self.make_request_headers(self.env.user),
+                timeout=default_timeout,
+            ).json()
             error = results.get("error")
             if error:
                 raise UserError(f"{error.get('code')}\n{error.get('message')}")
@@ -130,7 +144,11 @@ class SharepointMixin(models.AbstractModel):
 
         try:
             url = f"{ms_graph_site_url}/{site_id}/drives"
-            results = requests.get(url, headers=self.make_request_headers(self.env.user)).json()
+            results = requests.get(
+                url,
+                headers=self.make_request_headers(self.env.user),
+                timeout=default_timeout,
+            ).json()
             error = results.get("error")
             if error:
                 raise Exception(error.get("code", "Error"))
diff --git a/prettier.config.cjs b/prettier.config.cjs
new file mode 100644
index 0000000..e66cd82
--- /dev/null
+++ b/prettier.config.cjs
@@ -0,0 +1,14 @@
+/** @type {import('prettier').Config} */
+
+const config = {
+  // https://github.com/prettier/prettier/issues/15388#issuecomment-1717746872
+  plugins: [require.resolve("@prettier/plugin-xml")],
+  bracketSpacing: false,
+  printWidth: 88,
+  proseWrap: "always",
+  semi: true,
+  trailingComma: "es5",
+  xmlWhitespaceSensitivity: "preserve",
+};
+
+module.exports = config;
diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv
index c244372..a93d20c 100644
--- a/security/ir.model.access.csv
+++ b/security/ir.model.access.csv
@@ -1,2 +1,2 @@
-id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-"access_auth_oauth_provider","auth_oauth_provider all","model_auth_oauth_provider","base.group_user",1,0,0,0
\ No newline at end of file
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+"access_auth_oauth_provider","auth_oauth_provider all","model_auth_oauth_provider","base.group_user",1,0,0,0
diff --git a/views/res_config_settings.xml b/views/res_config_settings.xml
index 41dab06..6474cea 100644
--- a/views/res_config_settings.xml
+++ b/views/res_config_settings.xml
@@ -1,36 +1,36 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <odoo>
-    <record id="res_config_settings_financial_contract_view_form" model="ir.ui.view">
-        <field name="name">res.config.settings.view.financial.contract_form.inherit</field>
-        <field name="model">res.config.settings</field>
-        <field name="priority" eval="40" />
-        <field name="inherit_id" ref="base.res_config_settings_view_form" />
-        <field name="arch" type="xml">
-            <xpath expr="//form" position="inside">
-                <app
-                    data-string="Administrateur sharepoint"
-                    string="Administrateur sharepoint"
-                    name="admin_sharepoint"
-                >
-                    <block title="Administrateur sharepoint" name="admin_sharepoint">
-                        <setting>
-                            <field  name="admin_sharepoint_user_id" />
-                        </setting>
-                        <setting>
-                            <field  name="admin_sharepoint_secret_id" />
-                        </setting>
-                </block>
-                </app>
-            </xpath>
-        </field>
-    </record>
+  <record id="res_config_settings_financial_contract_view_form" model="ir.ui.view">
+    <field name="name">res.config.settings.view.financial.contract_form.inherit</field>
+    <field name="model">res.config.settings</field>
+    <field name="priority" eval="40" />
+    <field name="inherit_id" ref="base.res_config_settings_view_form" />
+    <field name="arch" type="xml">
+      <xpath expr="//form" position="inside">
+        <app
+          data-string="Administrateur sharepoint"
+          string="Administrateur sharepoint"
+          name="admin_sharepoint"
+        >
+          <block title="Administrateur sharepoint" name="admin_sharepoint">
+            <setting>
+              <field name="admin_sharepoint_user_id" />
+            </setting>
+            <setting>
+              <field name="admin_sharepoint_secret_id" />
+            </setting>
+          </block>
+        </app>
+      </xpath>
+    </field>
+  </record>
 
-    <record id="action_admin_sharepoint_config" model="ir.actions.act_window">
-        <field name="name">Settings</field>
-        <field name="type">ir.actions.act_window</field>
-        <field name="res_model">res.config.settings</field>
-        <field name="view_mode">form</field>
-        <field name="target">inline</field>
-        <field name="context">{'module' : 'siof_sharepoint', 'bin_size': False}</field>
-    </record>
+  <record id="action_admin_sharepoint_config" model="ir.actions.act_window">
+    <field name="name">Settings</field>
+    <field name="type">ir.actions.act_window</field>
+    <field name="res_model">res.config.settings</field>
+    <field name="view_mode">form</field>
+    <field name="target">inline</field>
+    <field name="context">{'module' : 'siof_sharepoint', 'bin_size': False}</field>
+  </record>
 </odoo>
diff --git a/views/res_partner_views.xml b/views/res_partner_views.xml
index 0bb7d1e..963cefe 100644
--- a/views/res_partner_views.xml
+++ b/views/res_partner_views.xml
@@ -1,29 +1,27 @@
 <?xml version="1.0" ?>
 <odoo>
-    <record model="ir.ui.view" id="view_partner_form_sharepoint">
-        <field name="name">res.partner.form.sharepoint</field>
-        <field name="model">res.partner</field>
-        <field name="inherit_id" ref="base.view_partner_form" />
-        <field name="arch" type="xml">
-             <xpath expr="//notebook" position="inside">
-                <page name="Sharepoint">
-                    <button
-                        name="action_redirect_to_sharepoint"
-                        string="Go to Sharepoint"
-                        type="object"
-                        class="btn-primary"
-                    />
+  <record model="ir.ui.view" id="view_partner_form_sharepoint">
+    <field name="name">res.partner.form.sharepoint</field>
+    <field name="model">res.partner</field>
+    <field name="inherit_id" ref="base.view_partner_form" />
+    <field name="arch" type="xml">
+      <xpath expr="//notebook" position="inside">
+        <page name="Sharepoint">
+          <button
+            name="action_redirect_to_sharepoint"
+            string="Go to Sharepoint"
+            type="object"
+            class="btn-primary"
+          />
 
-
-                    <button
-                        name="action_init_sharepoint"
-                        string="Init sharepoint"
-                        type="object"
-                        class="btn-primary"
-                    />
-
-                </page>
-             </xpath>
-        </field>
-    </record>
+          <button
+            name="action_init_sharepoint"
+            string="Init sharepoint"
+            type="object"
+            class="btn-primary"
+          />
+        </page>
+      </xpath>
+    </field>
+  </record>
 </odoo>
-- 
GitLab