diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..bfd7ac53df9f103f6dc8853738c63fd364445fde --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# Configuration for known file extensions +[*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{json,yml,yaml,rst,md}] +indent_size = 2 + +# Do not configure editor for libs and autogenerated content +[{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] +charset = unset +end_of_line = unset +indent_size = unset +indent_style = unset +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000000000000000000000000000000000000..d4cc423ccda9db9691205c9da83307af97b2670f --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,187 @@ +env: + browser: true + es6: true + +# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 +parserOptions: + ecmaVersion: 2017 + +overrides: + - files: + - "**/*.esm.js" + parserOptions: + sourceType: module + +# Globals available in Odoo that shouldn't produce errorings +globals: + _: readonly + $: readonly + fuzzy: readonly + jQuery: readonly + moment: readonly + odoo: readonly + openerp: readonly + owl: readonly + +# Styling is handled by Prettier, so we only need to enable AST rules; +# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 +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 + valid-jsdoc: + - warn + - prefer: + arg: param + argument: param + augments: extends + constructor: class + exception: throws + func: function + method: function + prop: property + return: returns + virtual: abstract + yield: yields + preferType: + array: Array + bool: Boolean + boolean: Boolean + number: Number + object: Object + str: String + string: String + requireParamDescription: false + requireReturn: false + requireReturnDescription: false + requireReturnType: false + valid-typeof: warn + yoda: warn diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000000000000000000000000000000000..e397e8ed4e3e7f7fe7785dd391bb80aa6d85575e --- /dev/null +++ b/.flake8 @@ -0,0 +1,12 @@ +[flake8] +max-line-length = 88 +max-complexity = 16 +# B = bugbear +# B9 = bugbear opinionated (incl line length) +select = C,E,F,W,B,B9 +# E203: whitespace before ':' (black behaviour) +# E501: flake8 line length (covered by bugbear B950) +# W503: line break before binary operator (black behaviour) +ignore = E203,E501,W503 +per-file-ignores= + __init__.py:F401 diff --git a/.gitignore b/.gitignore index 75bb2042901930f807a588241612a29dd75e34d5..818770fb1bdc0a144e924c9a5940f0b035df8a0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,75 @@ -.* -*.pyc -!.gitignore +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +/.venv +/.pytest_cache + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +bin/ +build/ +develop-eggs/ +dist/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +*.eggs + +# 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/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0ec187efd1bf802844749f508cda0c8f138970f9 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,13 @@ +[settings] +; see https://github.com/psf/black +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +combine_as_imports=True +use_parentheses=True +line_length=88 +known_odoo=odoo +known_odoo_addons=odoo.addons +sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER +default_section=THIRDPARTY +ensure_newline_before_comments = True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8a5999af4419f630dda23d9366b51967b8322ed3 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,127 @@ +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/| + # 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$| + # You don't usually want a bot to modify your legal texts + (LICENSE.*|COPYING.*) +default_language_version: + python: python3 + node: "14.13.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$" + - repo: https://github.com/oca/maintainer-tools + rev: ab1d7f6 + 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/myint/autoflake + rev: v1.4 + hooks: + - id: autoflake + args: + - --expand-star-imports + - --ignore-init-module-imports + - --in-place + - --remove-all-unused-imports + - --remove-duplicate-keys + - --remove-unused-variables + - repo: https://github.com/psf/black + rev: 20.8b1 + hooks: + - id: black + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.1.2 + hooks: + - id: prettier + name: prettier (with plugin-xml) + additional_dependencies: + - "prettier@2.1.2" + - "@prettier/plugin-xml@0.12.0" + args: + - --plugin=@prettier/plugin-xml + files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ + - repo: https://github.com/pre-commit/mirrors-eslint + rev: v7.8.1 + hooks: + - id: eslint + verbose: true + args: + - --color + - --fix + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.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/asottile/pyupgrade + rev: v2.7.2 + hooks: + - id: pyupgrade + args: ["--keep-percent-format"] + - repo: https://github.com/PyCQA/isort + rev: 5.5.1 + hooks: + - id: isort + name: isort except __init__.py + args: + - --settings=. + exclude: /__init__\.py$ + - repo: https://gitlab.com/PyCQA/flake8 + rev: 3.8.3 + hooks: + - id: flake8 + name: flake8 + additional_dependencies: ["flake8-bugbear==20.1.4"] + - repo: https://github.com/PyCQA/pylint + rev: pylint-2.5.3 + hooks: + - id: pylint + name: pylint with optional checks + args: + - --rcfile=.pylintrc + - --exit-zero + verbose: true + additional_dependencies: &pylint_deps + - pylint-odoo==3.5.0 + - id: pylint + name: pylint with mandatory checks + args: + - --rcfile=.pylintrc-mandatory + additional_dependencies: *pylint_deps diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 0000000000000000000000000000000000000000..5b6d4b361ace92f3877993bf2848fac190d8fab6 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,8 @@ +# Defaults for all prettier-supported languages. +# Prettier will complete this with settings from .editorconfig file. +bracketSpacing: false +printWidth: 88 +proseWrap: always +semi: true +trailingComma: "es5" +xmlWhitespaceSensitivity: "strict" diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000000000000000000000000000000000000..dc6270e15be0c08da00e768a570f27c785d8630e --- /dev/null +++ b/.pylintrc @@ -0,0 +1,87 @@ +[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=14.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, + # 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, + 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 0000000000000000000000000000000000000000..43ea23947166ff8080219007cfae43ec54a28f8e --- /dev/null +++ b/.pylintrc-mandatory @@ -0,0 +1,64 @@ +[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=14.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 + +[REPORTS] +msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} +output-format=colorized +reports=no diff --git a/README.rst b/README.rst old mode 100755 new mode 100644 diff --git a/__init__.py b/__init__.py old mode 100755 new mode 100644 index f88059b176b68c16a1a1024c635a43d555e9229c..5046b26cedea8504b44a6774586e23c5a7219caf --- a/__init__.py +++ b/__init__.py @@ -1,7 +1,4 @@ # © 2022 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import controllers -from . import models -from . import report -from . import wizard +from . import controllers, models, report, wizard diff --git a/__manifest__.py b/__manifest__.py old mode 100755 new mode 100644 index b8d7e6ddaef0a0b666927b58f682b85674600ffe..64b1d3682eaaa64843a37df6dbb516651a85bd44 --- a/__manifest__.py +++ b/__manifest__.py @@ -3,7 +3,7 @@ { "name": "CG SCOP - Cotisations CG", "summary": "CG SCOP - Cotisations CG Scop", - "version": "12.1.1.0", + "version": "14.0.1.0.0", "author": "Le Filament", "license": "AGPL-3", "application": False, @@ -14,6 +14,7 @@ "lefilament_export_journal_tool", "cgscop_cotisation", "queue_job_batch", + "web_progress", ], "data": [ # Security @@ -30,7 +31,7 @@ "templates/report_scop_bordereau_refund.xml", "templates/report_union_sociale.xml", # Views - "views/account_invoice.xml", + "views/account_move.xml", "views/res_config_settings.xml", "views/scop_cotisation_cg.xml", "views/scop_cotisation_simulation.xml", @@ -50,5 +51,10 @@ "views/scop_bordereau_cg.xml", # Menus "views/menus.xml", - ] + ], + "external_dependencies": { + "python": [ + "unidecode", + ], + }, } diff --git a/controllers/main.py b/controllers/main.py index 4165650cd0cff0006249e387db402e099ded0f20..8c6b946a2cec9159edd2d1283bb660ce436eb159 100644 --- a/controllers/main.py +++ b/controllers/main.py @@ -2,27 +2,34 @@ # License AGPL-3 or later (http://www.gnu.org/licenses/agpl.html). import csv -import unidecode from datetime import date, datetime from io import StringIO +import unidecode + from odoo import http from odoo.http import request -from odoo.addons.web.controllers.main import serialize_exception -from odoo.addons.web.controllers.main import content_disposition + +from odoo.addons.web.controllers.main import content_disposition, serialize_exception class ExportJournalCg(http.Controller): # ------------------------------------------------------ # Routes # ------------------------------------------------------ - @http.route('/web/export_journal_cg/', type='http', auth="user") + @http.route("/web/export_journal_cg/", type="http", auth="user") @serialize_exception def export_journal_cg( - self, company_id, - date_start=False, date_end=False, - date_creation_start=False, date_creation_end=False, - partner_ids=False, export_type='empty', **kwargs): + self, + company_id, + date_start=False, + date_end=False, + date_creation_start=False, + date_creation_end=False, + partner_ids=False, + export_type="empty", + **kwargs + ): """ Sélectionne les account.move.line correspondants aux journaux et à la plage de date définis @@ -38,37 +45,50 @@ class ExportJournalCg(http.Controller): :return: file """ # Get accounts variables - company_id = request.env['res.company'].browse(int(company_id)) - default_receivable_account_id = request.env.ref('l10n_fr.1_fr_pcg_recv') + company_id = request.env["res.company"].browse(int(company_id)) + default_receivable_account_id = request.env.ref("l10n_fr.1_fr_pcg_recv") contribution_cg_id = company_id.contribution_cg_id - contribution_ur_or_fede_journal_id = company_id.contribution_ur_or_fede_journal_id + + # Journaux des UR et Fédé + # TODO: vérifier l'export des comptes de banque en sortie pour UR et Fédé + journal_fede_com_id = company_id.company_id.journal_fede_com_id + journal_fede_cae_id = company_id.company_id.journal_fede_cae_id + journal_ur_hdf_id = company_id.company_id.journal_ur_hdf_id + journal_ur_med_id = company_id.company_id.journal_ur_med_id + journal_ids = [ + journal_fede_com_id.id, + journal_fede_cae_id.id, + journal_ur_hdf_id.id, + journal_ur_med_id.id, + ] + product_adhesion_id = company_id.product_adhesion_id journal_adhesion_id = company_id.journal_adhesion_id contribution_journal_id = company_id.contribution_journal_id # Selection des dates + pas d'export du journal UR / FEDE domain = [ - ('partner_id', '!=', False), - ('journal_id', '!=', contribution_ur_or_fede_journal_id.id), + ("partner_id", "!=", False), + ("journal_id", "not in", journal_ids), ] if date_start and date_end: domain += [ - ('date', '>=', date_start), - ('date', '<=', date_end), + ("date", ">=", date_start), + ("date", "<=", date_end), ] if date_creation_start and date_creation_end: domain += [ - ('create_date', '>=', date_creation_start), - ('create_date', '<=', date_creation_end), + ("create_date", ">=", date_creation_start), + ("create_date", "<=", date_creation_end), ] - if export_type == 'empty': - domain += [('date_export', '=', False)] + if export_type == "empty": + domain += [("date_export", "=", False)] # adds partner in domain if partner_ids: - domain += [('partner_id', 'in', list(map(int, partner_ids.split(","))))] + domain += [("partner_id", "in", list(map(int, partner_ids.split(","))))] - export_line_ids = request.env['account.move.line'].search(domain) + export_line_ids = request.env["account.move.line"].search(domain) lines_to_export = [] for line in export_line_ids: @@ -76,76 +96,117 @@ class ExportJournalCg(http.Controller): direction = self._move_direction(line) # Produit cotisation CG + Analytique if line.product_id == contribution_cg_id: - amount_analytic = round(1/3 * amount, 2) + amount_analytic = round(1 / 3 * amount, 2) # Compte général - lines_to_export.append(self._export_row( - line=line, amount=amount, direction=direction, - account=('7060' + line.partner_id.ur_id.code_ur)) + lines_to_export.append( + self._export_row( + line=line, + amount=amount, + direction=direction, + account=("7060" + line.partner_id.ur_id.code_ur), + ) ) # Lignes analytiques - lines_to_export.append(self._export_row( - line=line, amount=amount_analytic, direction=direction, - account=('7060' + line.partner_id.ur_id.code_ur), a_type='A', - analytic='010000') + lines_to_export.append( + self._export_row( + line=line, + amount=amount_analytic, + direction=direction, + account=("7060" + line.partner_id.ur_id.code_ur), + a_type="A", + analytic="010000", + ) ) # Produit Adhésion CG + Analytique + OD elif line.product_id == product_adhesion_id: - amount_analytic = round(1 / 2 * amount, 2) # Compte général - lines_to_export.append(self._export_row( - line=line, amount=amount, direction=direction, - journal='VE', account='756200') + lines_to_export.append( + self._export_row( + line=line, + amount=amount, + direction=direction, + journal="VE", + account="756200", + ) ) # Lignes analytiques - lines_to_export.append(self._export_row( - line=line, amount=amount, direction=direction, - account='756200', journal='VE', a_type='A', - analytic='010000') + lines_to_export.append( + self._export_row( + line=line, + amount=amount, + direction=direction, + account="756200", + journal="VE", + a_type="A", + analytic="010000", + ) ) # OD Adhésion - lines_to_export.append(self._export_row( - line=line, amount=amount/2, direction=direction, - account=('4660' + line.partner_id.ur_id.code_ur), - journal='OD') + lines_to_export.append( + self._export_row( + line=line, + amount=amount / 2, + direction=direction, + account=("4660" + line.partner_id.ur_id.code_ur), + journal="OD", + ) ) - lines_to_export.append(self._export_row( - line=line, amount=amount / 2, direction='D', - account=('6581' + line.partner_id.ur_id.code_ur), - journal='OD',) + lines_to_export.append( + self._export_row( + line=line, + amount=amount / 2, + direction="D", + account=("6581" + line.partner_id.ur_id.code_ur), + journal="OD", + ) ) - lines_to_export.append(self._export_row( - line=line, amount=amount / 2, direction='D', - account=('6581' + line.partner_id.ur_id.code_ur), - journal='OD', a_type='A', analytic='010000') + lines_to_export.append( + self._export_row( + line=line, + amount=amount / 2, + direction="D", + account=("6581" + line.partner_id.ur_id.code_ur), + journal="OD", + a_type="A", + analytic="010000", + ) ) - # Compte client CG Scop - Adhésion & Cotisation + # Compte client CG Scop - Adhésion & Cotisation journaux de vente elif line.account_id == default_receivable_account_id: if line.journal_id == journal_adhesion_id: - journal = 'VE' + journal = "VE" elif line.journal_id == contribution_journal_id: - journal = 'CO' + journal = "CO" else: - journal = 'EF' + journal = "EF" # Compte général - lines_to_export.append(self._export_row( - line=line, amount=amount, direction=direction, - account=('4112' + line.partner_id.ur_id.code_ur), - adh_account=self._get_partner_number(line.partner_id), - journal=journal) + lines_to_export.append( + self._export_row( + line=line, + amount=amount, + direction=direction, + account=("4112" + line.partner_id.ur_id.code_ur), + adh_account=self._get_partner_number(line.partner_id), + journal=journal, + ) ) # Banque else: - lines_to_export.append(self._export_row( - line=line, amount=amount, direction=direction, - account=line.account_id.code, journal='EF') + lines_to_export.append( + self._export_row( + line=line, + amount=amount, + direction=direction, + account=line.account_id.code, + journal="EF", + ) ) - line.write({ - 'date_export': datetime.now() - }) + line.write({"date_export": datetime.now()}) - filename_ = ('Export CG Scop - ' - + datetime.strftime(datetime.now(), "%Y-%m-%d_%Hh%S")) + filename_ = "Export CG Scop - " + datetime.strftime( + datetime.now(), "%Y-%m-%d_%Hh%S" + ) return self.export_cg_csv(lines_to_export, filename_) @@ -153,20 +214,29 @@ class ExportJournalCg(http.Controller): # Common function # ------------------------------------------------------ def _export_row( - self, line, amount, direction, account=None, - adh_account=None, a_type='G', journal=None, - analytic=None,): + self, + line, + amount, + direction, + account=None, + adh_account=None, + a_type="G", + journal=None, + analytic=None, + ): # Sanitize N° Bordereau if line.invoice_id.bordereau_id.name: inv_num = line.invoice_id.bordereau_id.name - elif line.full_reconcile_id.reconciled_line_ids.mapped('invoice_id'): - inv_num = line.full_reconcile_id.reconciled_line_ids.mapped('invoice_id')[0].bordereau_id.name + elif line.full_reconcile_id.reconciled_line_ids.mapped("invoice_id"): + inv_num = line.full_reconcile_id.reconciled_line_ids.mapped("invoice_id")[ + 0 + ].bordereau_id.name else: - inv_num = '' + inv_num = "" # Libellé description = line.partner_id.name.upper() if line.name: - description += ' - ' + line.name.upper() + description += " - " + line.name.upper() description = unidecode.unidecode(description) @@ -176,25 +246,25 @@ class ExportJournalCg(http.Controller): journal_code = line.journal_id.code return [ - line.move_id.name, # N° pièce - line.date, # Date pièce - line.date_maturity, # Date échéance - journal_code, # Journal - a_type, # Type d'écriture (général/analytique) - account, # Compte comptable - adh_account, # Num adh - description, # Libellé - direction, # Sens - amount, # Montant - inv_num, # N° Bordereau - analytic, # Code analytique + line.move_id.name, # N° pièce + line.date, # Date pièce + line.date_maturity, # Date échéance + journal_code, # Journal + a_type, # Type d'écriture (général/analytique) + account, # Compte comptable + adh_account, # Num adh + description, # Libellé + direction, # Sens + amount, # Montant + inv_num, # N° Bordereau + analytic, # Code analytique ] def _move_direction(self, line): if line.credit > 0.0: - return 'C' + return "C" else: - return 'D' + return "D" def _move_amount(self, line): if line.credit > 0: @@ -203,32 +273,33 @@ class ExportJournalCg(http.Controller): return line.debit def _get_partner_number(self, partner): - number = partner.member_number + '00' + number = partner.member_number + "00" prefix = 8 - len(number) - return (prefix * '0') + number + return (prefix * "0") + number def export_cg_csv(self, lines_to_export, filename_): fp = StringIO() export_file = csv.writer( fp, - delimiter=';', - dialect='excel', + delimiter=";", + dialect="excel", ) # Add header line for line in lines_to_export: # Format date value line_values = [ - value if not isinstance(value, date) else value.strftime( - "%d/%m/%Y") for value in line] + value if not isinstance(value, date) else value.strftime("%d/%m/%Y") + for value in line + ] export_file.writerow(line_values) fp.seek(0) data = fp.read() fp.close() - filename = filename_ + '.txt' + filename = filename_ + ".txt" csvhttpheaders = [ - ('Content-Type', 'text/plain;charset=iso-8859-1'), - ('Content-Disposition', content_disposition(filename)), + ("Content-Type", "text/plain;charset=iso-8859-1"), + ("Content-Disposition", content_disposition(filename)), ] return request.make_response(data, headers=csvhttpheaders) diff --git a/controllers/union_sociale.py b/controllers/union_sociale.py index 41968a263e58dbef23cf12ede73df2ae6e21d8cb..99c9cdadfb7c46c82c8a7eb86d8e04f5d2718c79 100644 --- a/controllers/union_sociale.py +++ b/controllers/union_sociale.py @@ -12,9 +12,13 @@ class UnionSocialeController(http.Controller): # Routes # ------------------------------------------------------ @http.route( - ['/union-sociale/<adh>', - '/union-sociale/<adh>/<year>'], - type='http', auth="public", method=['GET'], csrf=False, website=False) + ["/union-sociale/<adh>", "/union-sociale/<adh>/<year>"], + type="http", + auth="public", + method=["GET"], + csrf=False, + website=False, + ) def get_union_sociale_pdf(self, adh, year=False): """ URL pour générer le PDF de l'Union Sociale à joindre au @@ -23,15 +27,19 @@ class UnionSocialeController(http.Controller): :params : year -> année du bordereau @return : PDF """ - partner_id = request.env['res.partner'].sudo().search([('member_number', '=', adh)]) + partner_id = ( + request.env["res.partner"].sudo().search([("member_number", "=", adh)]) + ) if partner_id: - ctx = {'year': int(year)} if year else {} + ctx = {"year": int(year)} if year else {} # Get report - report = request.env.ref('cgscop_cotisation_cg.cgscop_union_sociale_report') + report = request.env.ref("cgscop_cotisation_cg.cgscop_union_sociale_report") # Create PDF pdf = report.sudo().with_context(ctx).render_qweb_pdf([partner_id.id])[0] - pdfhttpheaders = [('Content-Type', 'application/pdf'), - ('Content-Length', len(pdf)), ] + pdfhttpheaders = [ + ("Content-Type", "application/pdf"), + ("Content-Length", len(pdf)), + ] # Return PDF return request.make_response(pdf, headers=pdfhttpheaders) else: diff --git a/datas/bordereau_refund_wizard_quarter_data.xml b/datas/bordereau_refund_wizard_quarter_data.xml index 213e9e1c3c7d87a3994aa33dae104d47dce78123..e048f8e6dfead2d224af6cf24d79ff7bf2c898dc 100644 --- a/datas/bordereau_refund_wizard_quarter_data.xml +++ b/datas/bordereau_refund_wizard_quarter_data.xml @@ -1,24 +1,36 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament (<https://www.le-filament.com>) License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). --> <odoo> <data noupdate="1"> - <record id="bordereau_wizard_quarter1" model="scop.bordereau.refund.wizard.quarter"> + <record + id="bordereau_wizard_quarter1" + model="scop.bordereau.refund.wizard.quarter" + > <field name="quarter">1</field> </record> - <record id="bordereau_wizard_quarter2" model="scop.bordereau.refund.wizard.quarter"> + <record + id="bordereau_wizard_quarter2" + model="scop.bordereau.refund.wizard.quarter" + > <field name="quarter">2</field> </record> - - <record id="bordereau_wizard_quarter3" model="scop.bordereau.refund.wizard.quarter"> + + <record + id="bordereau_wizard_quarter3" + model="scop.bordereau.refund.wizard.quarter" + > <field name="quarter">3</field> </record> - - <record id="bordereau_wizard_quarter4" model="scop.bordereau.refund.wizard.quarter"> + + <record + id="bordereau_wizard_quarter4" + model="scop.bordereau.refund.wizard.quarter" + > <field name="quarter">4</field> </record> - + </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/datas/ir_sequence_data.xml b/datas/ir_sequence_data.xml index 6409aac44e23e771de9a9fbf90fbb728d97c1989..1d8618923066f7ba61802328c7f9f97ff1e10120 100644 --- a/datas/ir_sequence_data.xml +++ b/datas/ir_sequence_data.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data noupdate="1"> @@ -7,7 +7,7 @@ <field name="code">scop.bordereau</field> <field name="padding">4</field> <field name="prefix">CG%(year)s</field> - <field name="company_id" ref="base.main_company"/> + <field name="company_id" ref="base.main_company" /> </record> </data> diff --git a/datas/mail_data.xml b/datas/mail_data.xml index c4672057b2a8b6bf5de6604bafca41997f7fd1d6..ad475e8ea861a57e004c73044b6113f5a6378bae 100644 --- a/datas/mail_data.xml +++ b/datas/mail_data.xml @@ -1,14 +1,18 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> - <data noupdate="0"> + <data> <!-- Template and notification section --> <record id="email_template_cotisation_cg" model="mail.template"> <field name="name">Cotisation CG SCOP : Génération du bordereau</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau"/> - <field name="email_from">"Confédération Générale des Scop et Scic" <administratif.cg@scop.coop></field> - <field name="reply_to">"Confédération Générale des Scop et Scic" <administratif.cg@scop.coop></field> + <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau" /> + <field + name="email_from" + >"Confédération Générale des Scop et Scic" <administratif.cg@scop.coop></field> + <field + name="reply_to" + >"Confédération Générale des Scop et Scic" <administratif.cg@scop.coop></field> <field name="partner_to">${object.get_recipients()}</field> <field name="subject">CG SCOP : Appel de cotisations ${object.year}</field> <field name="body_html" type="html"> @@ -18,20 +22,23 @@ <p>Cotisation sur votre espace extranet : lien</p> - <p>Vous pouvez également télécharger le lien du bordereau de cotisation à l'Union sociale en cliquant sur le lien suivant : <a href="/union-sociale/${object.partner_id.member_number}/${object.year}">bordereau de l'union sociale</a></p> + <p + >Vous pouvez également télécharger le lien du bordereau de cotisation à l'Union sociale en cliquant sur le lien suivant : <a + href="/union-sociale/${object.partner_id.member_number}/${object.year}" + >bordereau de l'union sociale</a></p> - <p>Nous vous prions d'agréer, Chère Coopératrice, Cher Coopérateur, nos sentiments les meilleurs.</p> + <p + >Nous vous prions d'agréer, Chère Coopératrice, Cher Coopérateur, nos sentiments les meilleurs.</p> <p>Pour la CG Scop,</p> - + <p>JACQUES LANDRIOT</p> <p>Président</p> </p> </div> </field> <field name="lang">fr_FR</field> - <field name="user_signature" eval="False"/> - <field name="auto_delete" eval="False"/> + <field name="auto_delete" eval="False" /> </record> </data> diff --git a/datas/queue_job_data.xml b/datas/queue_job_data.xml index 97e8623f45d7ae4c8eee9f57cf976c1fd4e074f8..e55a03577ca2e8de95c9702bdb5ccc9c0c8e8b07 100644 --- a/datas/queue_job_data.xml +++ b/datas/queue_job_data.xml @@ -1,24 +1,39 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament (<https://www.le-filament.com>) License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). --> <odoo> <data noupdate="1"> - <record id="job_function_cotisation_cg_create_bordereau" model="queue.job.function"> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_cotisation_cg" /> + <record + id="job_function_cotisation_cg_create_bordereau" + model="queue.job.function" + > + <field + name="model_id" + ref="cgscop_cotisation_cg.model_scop_cotisation_cg" + /> <field name="method">create_bordereau</field> <field name="channel_id" ref="queue_job.channel_root" /> - <field name="related_action" eval='{"func_name": "related_action_custom", "kwargs": {"model": "scop.bordereau", "record": "result"}}' /> + <field + name="related_action" + eval='{"func_name": "related_action_custom", "kwargs": {"model": "scop.bordereau", "record": "result"}}' + /> <field name="retry_pattern" eval="{1: 10, 5: 30, 10: 300}" /> </record> - <record id="job_function_cotisation_cg_validate_bordereau" model="queue.job.function"> + <record + id="job_function_cotisation_cg_validate_bordereau" + model="queue.job.function" + > <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau" /> <field name="method">validate_bordereau</field> <field name="channel_id" ref="queue_job.channel_root" /> - <field name="related_action" eval='{"func_name": "related_action_custom"}' /> + <field + name="related_action" + eval='{"func_name": "related_action_custom"}' + /> <field name="retry_pattern" eval="{1: 10, 5: 30, 10: 300}" /> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/migration/14.0.1.0.0/post-migration.py b/migration/14.0.1.0.0/post-migration.py new file mode 100644 index 0000000000000000000000000000000000000000..36aed2219d849c3a83fbae446328a228ff03f4db --- /dev/null +++ b/migration/14.0.1.0.0/post-migration.py @@ -0,0 +1,40 @@ +# © 2022 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openupgradelib import openupgrade # pylint: disable=W7936 + + +def scop_account_move_cg_map_values(env): + openupgrade.map_values( + env.cr, + openupgrade.get_legacy_name("cotiz_quarter"), + "account_move", + [ + (1, "1"), + (2, "2"), + (3, "3"), + (4, "4"), + ], + table="account_move", + ) + + +def scop_bordereau_map_values(env): + openupgrade.map_values( + env.cr, + openupgrade.get_legacy_name("nb_quarter"), + "scop_bordereau", + [ + (1, "1"), + (2, "2"), + (3, "3"), + (4, "4"), + ], + table="scop_bordereau", + ) + + +@openupgrade.migrate() +def migrate(env, version): + scop_account_move_cg_map_values(env) + scop_bordereau_map_values(env) diff --git a/migration/14.0.1.0.0/pre-migration.py b/migration/14.0.1.0.0/pre-migration.py new file mode 100644 index 0000000000000000000000000000000000000000..e43945427cabfc39b3a387fdee3cb5c2efec1ae3 --- /dev/null +++ b/migration/14.0.1.0.0/pre-migration.py @@ -0,0 +1,14 @@ +# © 2022 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openupgradelib import openupgrade + +column_renames = { + "account_move": [("cotiz_quarter", None)], + "scop_bordereau": [("nb_quarter", None)], +} + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.rename_columns(env.cr, column_renames) diff --git a/models/__init__.py b/models/__init__.py old mode 100755 new mode 100644 index c34981509f9c6ecfd42f18c4df619cc48a4f5832..872bf77fa50794bcb5d32174b7da337c69a919a0 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,7 +1,7 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import account_invoice +from . import account_move from . import res_company from . import res_config_settings from . import scop_bordereau_cg diff --git a/models/account_invoice.py b/models/account_invoice.py deleted file mode 100644 index b8c7e828bc0d64344d0483b78f2232874293c81d..0000000000000000000000000000000000000000 --- a/models/account_invoice.py +++ /dev/null @@ -1,47 +0,0 @@ -# © 2021 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, api - - -class ScopAccountInvoiceCG(models.Model): - _inherit = "account.invoice" - - bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau de rattachement', - ondelete='cascade', - required=False,) - cotisation_cg_id = fields.Many2one( - related='bordereau_id.base_cotisation_cg') - amount_cg_calculated = fields.Monetary( - string="Montant cotisation annuel", - currency_field='company_currency_id', readonly=True) - nb_quarter = fields.Selection(related='bordereau_id.nb_quarter') - cotiz_quarter = fields.Selection( - string='Trimestre', - selection=[(1, 1), (2, 2), (3, 3), (4, 4)], - required=False, ) - - # ------------------------------------------------------ - # Compute fields - # ------------------------------------------------------ - - # ------------------------------------------------------ - # Override parent - # ------------------------------------------------------ - - # ------------------------------------------------------ - # Global functions - # ------------------------------------------------------ - def view_cotiz(self): - form_view = self.env.ref( - 'cgscop_cotisation_cg.invoice_form_scop_cg_inherited').id - return { - 'name': "Cotisation", - 'type': 'ir.actions.act_window', - 'res_model': 'account.invoice', - 'views': [[form_view, 'form']], - 'res_id': self.id, - 'target': 'current', - } diff --git a/models/account_move.py b/models/account_move.py new file mode 100644 index 0000000000000000000000000000000000000000..b92e499b79187aecd5ce90ffb1a8a2851cbc07d8 --- /dev/null +++ b/models/account_move.py @@ -0,0 +1,51 @@ +# © 2021 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ScopAccountMove(models.Model): + _inherit = "account.move" + + bordereau_id = fields.Many2one( + comodel_name="scop.bordereau", + string="Bordereau de rattachement", + ondelete="cascade", + required=False, + ) + cotisation_cg_id = fields.Many2one(related="bordereau_id.base_cotisation_cg") + amount_cg_calculated = fields.Monetary( + string="Montant cotisation annuel", + currency_field="company_currency_id", + readonly=True, + ) + nb_quarter = fields.Selection(related="bordereau_id.nb_quarter") + cotiz_quarter = fields.Selection( + string="Trimestre", + selection=[("1", "1"), ("2", "2"), ("3", "3"), ("4", "4")], + required=False, + ) + + # ------------------------------------------------------ + # Compute fields + # ------------------------------------------------------ + + # ------------------------------------------------------ + # Override parent + # ------------------------------------------------------ + + # ------------------------------------------------------ + # Global functions + # ------------------------------------------------------ + def view_cotiz(self): + form_view = self.env.ref( + "cgscop_cotisation_cg.invoice_form_scop_cg_inherited" + ).id + return { + "name": "Cotisation", + "type": "ir.actions.act_window", + "res_model": "account.invoice", + "views": [[form_view, "form"]], + "res_id": self.id, + "target": "current", + } diff --git a/models/res_company.py b/models/res_company.py index 459f8dde08d2afe81f8cb140f8e33fc3e1887fbd..183ab32106c4929814c3e9936a11170fe838a4fc 100644 --- a/models/res_company.py +++ b/models/res_company.py @@ -5,59 +5,51 @@ from odoo import fields, models class ScopCotisationCGCompany(models.Model): - _inherit = 'res.company' + _inherit = "res.company" - is_contribution_cg = fields.Boolean( - string='Cotisations CG Scop' - ) + is_contribution_cg = fields.Boolean(string="Cotisations CG Scop") contribution_cg_id = fields.Many2one( - comodel_name='product.product', - string='Article de cotisation CG', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + comodel_name="product.product", + string="Article de cotisation CG", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) contribution_fede_com_id = fields.Many2one( - comodel_name='product.product', - string='Article de cotisation Fédé de la Com', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + comodel_name="product.product", + string="Article de cotisation Fédé de la Com", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_fede_com_id = fields.Many2one( - comodel_name='account.account', - string="Compte de tiers Fédération de la com", - domain="[('internal_type', '=', 'receivable')]", + journal_fede_com_id = fields.Many2one( + comodel_name="account.journal", + string="Journal Fédération de la com", + domain="[('type', '=', 'sale')]", ) contribution_fede_cae_id = fields.Many2one( - comodel_name='product.product', - string='Article de cotisation Fédé CAE', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + comodel_name="product.product", + string="Article de cotisation Fédé CAE", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_fede_cae_id = fields.Many2one( - comodel_name='account.account', - string="Compte de tiers Fédération CAE", - domain="[('internal_type', '=', 'receivable')]", + journal_fede_cae_id = fields.Many2one( + comodel_name="account.journal", + string="Journal Fédération CAE", + domain="[('type', '=', 'sale')]", ) contribution_hdf_id = fields.Many2one( - comodel_name='product.product', - string='Article de cotisation UR HDF', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + comodel_name="product.product", + string="Article de cotisation UR HDF", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_ur_hdf_id = fields.Many2one( - comodel_name='account.account', - string="Compte de tiers UR HDF", - domain="[('internal_type', '=', 'receivable')]", + journal_ur_hdf_id = fields.Many2one( + comodel_name="account.journal", + string="Journal UR HDF", + domain="[('type', '=', 'sale')]", ) contribution_med_id = fields.Many2one( - comodel_name='product.product', - string='Article de cotisation UR Méditerranée', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" - ) - receivable_account_ur_med_id = fields.Many2one( - comodel_name='account.account', - string="Compte de tiers UR Med", - domain="[('internal_type', '=', 'receivable')]", + comodel_name="product.product", + string="Article de cotisation UR Méditerranée", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - - contribution_ur_or_fede_journal_id = fields.Many2one( - comodel_name='account.journal', - string='Journal des cotisations UR ou Fédérations', + journal_ur_med_id = fields.Many2one( + comodel_name="account.journal", + string="Journal UR Med", domain="[('type', '=', 'sale')]", ) diff --git a/models/res_config_settings.py b/models/res_config_settings.py index a6b6e0122b224a3717f8072d91e808d02db6d784..0fa5f7caeb6489ca81e9a24153019fca9776c0b9 100644 --- a/models/res_config_settings.py +++ b/models/res_config_settings.py @@ -1,113 +1,82 @@ # © 2020 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models, api +from odoo import api, fields, models class CotisationsConfigSettings(models.TransientModel): - _inherit = 'res.config.settings' + _inherit = "res.config.settings" is_contribution_cg = fields.Boolean( - string='Cotisations CG Scop', + string="Cotisations CG Scop", related="company_id.is_contribution_cg", - readonly=False) + readonly=False, + ) contribution_cg_id = fields.Many2one( - comodel_name='product.product', + comodel_name="product.product", related="company_id.contribution_cg_id", readonly=False, - string='Article de cotisation CG', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + string="Article de cotisation CG", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) contribution_fede_com_id = fields.Many2one( - comodel_name='product.product', + comodel_name="product.product", related="company_id.contribution_fede_com_id", readonly=False, - string='Article de cotisation Fédé de la Com', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + string="Article de cotisation Fédé de la Com", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_fede_com_id = fields.Many2one( - comodel_name='account.account', - related="company_id.receivable_account_fede_com_id", + journal_fede_com_id = fields.Many2one( + comodel_name="account.journal", + related="company_id.journal_fede_com_id", readonly=False, - string="Compte de tiers Fédération de la com", - domain="[('internal_type', '=', 'receivable')]", + string="Journal Fédération de la com", + domain="[('type', '=', 'sale')]", ) contribution_fede_cae_id = fields.Many2one( - comodel_name='product.product', + comodel_name="product.product", related="company_id.contribution_fede_cae_id", readonly=False, - string='Article de cotisation Fédé CAE', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + string="Article de cotisation Fédé CAE", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_fede_cae_id = fields.Many2one( - comodel_name='account.account', - related="company_id.receivable_account_fede_cae_id", + journal_fede_cae_id = fields.Many2one( + comodel_name="account.journal", + related="company_id.journal_fede_cae_id", readonly=False, - string="Compte de tiers Fédération CAE", - domain="[('internal_type', '=', 'receivable')]", + string="Journal Fédération CAE", + domain="[('type', '=', 'sale')]", ) contribution_hdf_id = fields.Many2one( - comodel_name='product.product', + comodel_name="product.product", related="company_id.contribution_hdf_id", readonly=False, - string='Article de cotisation UR HDF', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + string="Article de cotisation UR HDF", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_ur_hdf_id = fields.Many2one( - comodel_name='account.account', - related="company_id.receivable_account_ur_hdf_id", + journal_ur_hdf_id = fields.Many2one( + comodel_name="account.journal", + related="company_id.journal_ur_hdf_id", readonly=False, - string="Compte de tiers UR HDF", - domain="[('internal_type', '=', 'receivable')]", + string="Journal UR HDF", + domain="[('type', '=', 'sale')]", ) contribution_med_id = fields.Many2one( - comodel_name='product.product', + comodel_name="product.product", related="company_id.contribution_med_id", readonly=False, - string='Article de cotisation UR Méditerranée', - domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]" + string="Article de cotisation UR Méditerranée", + domain="[('sale_ok', '=', True), ('company_id', '=', company_id)]", ) - receivable_account_ur_med_id = fields.Many2one( - comodel_name='account.account', - related="company_id.receivable_account_ur_med_id", + journal_ur_med_id = fields.Many2one( + comodel_name="account.journal", + related="company_id.journal_ur_med_id", readonly=False, - string="Compte de tiers UR Med", - domain="[('internal_type', '=', 'receivable')]", + string="Journal UR Med", + domain="[('type', '=', 'sale')]", ) - contribution_ur_or_fede_journal_id = fields.Many2one( - comodel_name='account.journal', - related="company_id.contribution_ur_or_fede_journal_id", - readonly=False, - string='Journal des cotisations UR ou Fédération', - domain="[('type', '=', 'sale')]") - - @api.onchange('is_contribution') + @api.onchange("is_contribution") def _onchange_is_contribution_cg(self): if not self.is_contribution: self.is_contribution_cg = False - - def execute(self): - """ - Rewrite execute() function to add current company to the list - of available company in ir_ui_menu - """ - res = super(CotisationsConfigSettings, self).execute() - - menu_appels_cotiz_cg = self.env.ref( - 'cgscop_cotisation_cg.menu_scop_cotisation_cg_appel_cotisation') - menu_cotiz_cg = self.env.ref( - 'cgscop_cotisation_cg.menu_scop_cotisation_cg_calcul') - menu_bordereaux_cg = self.env.ref( - 'cgscop_cotisation_cg.scop_bordereau_menu') - # menu_adhesions_cg = self.env.ref( - # 'cgscop_cotisation_cg.menu_scop_cotisation_cg_adhesions') - - - bool_condition = self.is_contribution_cg - - self.add_company_to_menu(menu_appels_cotiz_cg, bool_condition) - self.add_company_to_menu(menu_cotiz_cg, bool_condition) - self.add_company_to_menu(menu_bordereaux_cg, bool_condition) - # self.add_company_to_menu(menu_adhesions_cg, bool_condition) - return res diff --git a/models/scop_bordereau_cg.py b/models/scop_bordereau_cg.py index 13dd6e23b89bdb4ed01aebfe82b6602b32b3133b..24773fb335571734b3b6c1596c8396280176b0fd 100644 --- a/models/scop_bordereau_cg.py +++ b/models/scop_bordereau_cg.py @@ -1,182 +1,205 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models, api +from odoo import _, api, fields, models from odoo.exceptions import UserError class Bordereau(models.Model): - _name = 'scop.bordereau' - _description = 'Bordereau des cotisations CG' - _inherit = 'mail.thread' - _order = 'name desc' + _name = "scop.bordereau" + _description = "Bordereau des cotisations CG" + _inherit = "mail.thread" + _order = "name desc" name = fields.Char( - string='Référence du bordereau', - readonly=True, copy=False, default="Brouillon") - version = fields.Integer('Version', default=1, track_visibility='onchange') + string="Référence du bordereau", + readonly=True, + copy=False, + default="Brouillon", + ) + version = fields.Integer("Version", default=1, tracking=1) base_cotisation_cg = fields.Many2one( - comodel_name='scop.cotisation.cg', - string='Base de cotisation', + comodel_name="scop.cotisation.cg", + string="Base de cotisation", required=False, readonly=True, - ondelete='cascade') + ondelete="cascade", + ) year = fields.Char( - string='Année du bordereau', - compute='_compute_year', + string="Année du bordereau", + compute="_compute_year", store=True, - required=False) + required=False, + ) date_cotisation = fields.Date("Date de cotisation") - is_regul = fields.Boolean("Regularisation", defaut=False) + is_regul = fields.Boolean("Regularisation", default=False) date_regul = fields.Date("Date de régularisation") - comment_regul = fields.Char('Motif de régularisation') + comment_regul = fields.Char("Motif de régularisation") partner_id = fields.Many2one( - comodel_name='res.partner', - string='Adhérent', + comodel_name="res.partner", + string="Adhérent", required=False, readonly=True, - track_visibility='onchange') + tracking=1, + ) member_number = fields.Integer( - string='N° Adhérent', - related='partner_id.member_number_int') + string="N° Adhérent", related="partner_id.member_number_int" + ) liasse_fiscale_id = fields.Many2one( - comodel_name='scop.liasse.fiscale', - string='Liasse fiscale de référence', + comodel_name="scop.liasse.fiscale", + string="Liasse fiscale de référence", readonly=True, - track_visibility='onchange') + tracking=1, + ) liasse_count = fields.Integer( - string='Nombre de liasses', - compute='_compute_liasse_count' + string="Nombre de liasses", compute="_compute_liasse_count" ) type_liasse_fiscale = fields.Selection( - string='Type de liasse', - related='liasse_fiscale_id.type_id') + string="Type de liasse", related="liasse_fiscale_id.type_id" + ) is_liasse_previ = fields.Boolean( - 'Est une liasse prévisionnelle', - compute='_compute_is_liasse_previ') + "Est une liasse prévisionnelle", compute="_compute_is_liasse_previ" + ) dureeExercice = fields.Integer( - string='Durée de l’exercice', - related='liasse_fiscale_id.dureeExercice', - track_visibility='onchange') + string="Durée de l’exercice", + related="liasse_fiscale_id.dureeExercice", + tracking=1, + ) partner_ur_id = fields.Many2one( - comodel_name='union.regionale', - string='UR Adhérent', - related='partner_id.ur_id', - store=True + comodel_name="union.regionale", + string="UR Adhérent", + related="partner_id.ur_id", + store=True, ) payment_mode_id = fields.Many2one( - comodel_name='account.payment.mode', string="Mode de paiment", - ondelete='restrict', - readonly=True, states={'draft': [('readonly', False)]}, - track_visibility='onchange') + comodel_name="account.payment.mode", + string="Mode de paiment", + ondelete="restrict", + readonly=True, + states={"draft": [("readonly", False)]}, + tracking=1, + ) invoice_ids = fields.One2many( - comodel_name='account.invoice', - inverse_name='bordereau_id', - string='Cotisations', - required=False) + comodel_name="account.move", + inverse_name="bordereau_id", + string="Cotisations", + required=False, + ) invoice_count = fields.Integer( - string='Nombre d\'appels', - compute='_compute_invoice_count' + string="Nombre d'appels", compute="_compute_invoice_count" ) - state = fields.Selection([ - ('new', 'Brouillon'), - ('ongoing', 'En cours de modification'), - ('validated', 'Validé'), - ('paid', 'Payé'), - ('cancel', 'Annulé')], + state = fields.Selection( + [ + ("new", "Brouillon"), + ("ongoing", "En cours de modification"), + ("validated", "Validé"), + ("paid", "Payé"), + ("cancel", "Annulé"), + ], string="Statut", - default='new', - compute='_compute_state', store=True, - track_visibility='onchange', ) + default="new", + compute="_compute_state", + store=True, + tracking=1, + ) company_id = fields.Many2one( - comodel_name='res.company', - related='base_cotisation_cg.company_id', - string="Company" + comodel_name="res.company", + related="base_cotisation_cg.company_id", + string="Company", ) company_currency_id = fields.Many2one( - comodel_name='res.currency', - related='company_id.currency_id', - string="Company Currency", readonly=True) + comodel_name="res.currency", + related="company_id.currency_id", + string="Company Currency", + readonly=True, + ) amount_total_cotiz = fields.Monetary( - string='Montant total de(s) cotisation(s)', - currency_field='company_currency_id', - compute='_compute_amount_total_cotiz', - store=True) + string="Montant total de(s) cotisation(s)", + currency_field="company_currency_id", + compute="_compute_amount_total_cotiz", + store=True, + ) amount_residual = fields.Monetary( - string='Montant dû', - currency_field='company_currency_id', - compute='_compute_amount_residual', - store=True) + string="Montant dû", + currency_field="company_currency_id", + compute="_compute_amount_residual", + store=True, + ) nb_quarter = fields.Selection( - string='Nb de trimestres de cotisation', - selection=[(1, '1'), - (2, '2'), - (3, '3'), - (4, '4')], - default='4', required=True, - track_visibility='onchange') - details = fields.Html('Détails', compute='_compute_details') + string="Nb de trimestres de cotisation", + selection=[("1", "1"), ("2", "2"), ("3", "3"), ("4", "4")], + default="4", + required=True, + tracking=1, + ) + details = fields.Html("Détails", compute="_compute_details") # Assiettes for cotiz calcul year_liasse = fields.Integer( - string='Année de la liasse', - related='liasse_fiscale_id.year', - track_visibility='onchange', - oldname='year_liasse_retenue' + string="Année de la liasse", + related="liasse_fiscale_id.year", + tracking=1, ) type_assiette = fields.Selection( - related='liasse_fiscale_id.contribution_base_type', store=True) + related="liasse_fiscale_id.contribution_base_type", store=True + ) montant_assiette = fields.Integer( - related='liasse_fiscale_id.contribution_base_amount', store=True) + related="liasse_fiscale_id.contribution_base_amount", store=True + ) ca = fields.Float( - string='CA', - compute='_compute_values_calculation', store=True, - track_visibility='onchange', - oldname='ca_retenu') + string="CA", + compute="_compute_values_calculation", + store=True, + tracking=1, + ) va = fields.Float( - string='VA', - compute='_compute_values_calculation', store=True, - track_visibility='onchange', - oldname='va_cg_retenu') + string="VA", + compute="_compute_values_calculation", + store=True, + tracking=1, + ) staff_count = fields.Integer( - string='Effectif de la coop', - readonly=True, oldname='staff_count_connu') + string="Effectif de la coop", + readonly=True, + ) staff_shareholder_count = fields.Integer( - string='Effectif sociétaires de la coop', - readonly=True, oldname='staff_shareholder_count_retenu') + string="Effectif sociétaires de la coop", + readonly=True, + ) staff_average = fields.Float( - string='Effectif moyen de la coop', - readonly=True, oldname='staff_average_retenu') + string="Effectif moyen de la coop", + readonly=True, + ) net_results = fields.Float( - string='Résultat net', - compute='_compute_values_calculation', store=True, - oldname='net_results_retenu') + string="Résultat net", + compute="_compute_values_calculation", + store=True, + ) wage_cg = fields.Float( - string='Montant masse salariale', - compute='_compute_values_calculation', store=True, - oldname='wage_cg_retenu') + string="Montant masse salariale", + compute="_compute_values_calculation", + store=True, + ) is_sdd = fields.Boolean( - 'Au prélèvement', - compute='compute_is_sdd', - search='_search_is_sdd') + "Au prélèvement", compute="_compute_is_sdd", search="_search_is_sdd" + ) refund_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Nouveau bordereau', + comodel_name="scop.bordereau", + string="Nouveau bordereau", domain="[('partner_id', '=', partner_id)]", - track_visibility='onchange' + tracking=1, ) related_refund_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau initial', + comodel_name="scop.bordereau", + string="Bordereau initial", ) # Emails management recipient_ids = fields.One2many( - comodel_name='res.partner', - compute='_compute_recipient' + comodel_name="res.partner", compute="_compute_recipient" ) # TODO : Use when email active @@ -187,186 +210,191 @@ class Bordereau(models.Model): # Historique des versions bordereau_version_ids = fields.One2many( - comodel_name='scop.bordereau.version', - inverse_name='bordereau_id', - string='Historique' + comodel_name="scop.bordereau.version", + inverse_name="bordereau_id", + string="Historique", ) has_outstanding = fields.Boolean( - string='Paiements en circulation', - compute='_compute_has_outstanding', store=True + string="Paiements en circulation", + compute="_compute_has_outstanding", + store=True, ) # ------------------------------------------------------ # Compute # ------------------------------------------------------ - @api.depends('liasse_fiscale_id') - @api.multi + @api.depends("liasse_fiscale_id") def _compute_values_calculation(self): for r in self: if r.liasse_fiscale_id: liasse = r.liasse_fiscale_id r.ca = liasse.revenue_cgsubv r.va = r.base_cotisation_cg.get_va(liasse) - r.net_results = liasse.L2053_HN \ - if liasse.L2053_HN > 0 else liasse.L2051_DI + r.net_results = ( + liasse.L2053_HN if liasse.L2053_HN > 0 else liasse.L2051_DI + ) r.wage_cg = liasse.wage_cg else: r.ca = r.va = r.net_results = r.wage_cg = 0 - @api.depends('invoice_ids.state', - 'bordereau_version_ids', 'bordereau_version_ids.state') - @api.multi + @api.depends( + "invoice_ids.state", + "invoice_ids.payment_state", + "bordereau_version_ids", + "bordereau_version_ids.state", + ) def _compute_state(self): for bordereau in self: draft_cotiz = bordereau.invoice_ids.filtered( - lambda cotiz: cotiz.state == 'draft' + lambda cotiz: cotiz.state == "draft" ) ongoing_version = bordereau.bordereau_version_ids.filtered( - lambda v: v.state == 'new' + lambda v: v.state == "new" ) if ongoing_version: - bordereau.state = 'ongoing' + bordereau.state = "ongoing" elif draft_cotiz: - bordereau.state = 'new' + bordereau.state = "new" else: unpaid_cotiz = bordereau.invoice_ids.filtered( - lambda cotiz: cotiz.state not in ('paid', 'cancel') + lambda cotiz: cotiz.payment_state not in ("paid", "cancel") ) if not unpaid_cotiz: - bordereau.state = 'paid' + bordereau.state = "paid" else: - bordereau.state = 'validated' + bordereau.state = "validated" - @api.depends('base_cotisation_cg') - @api.multi + @api.depends("base_cotisation_cg") def _compute_year(self): for bordereau in self: bordereau.year = bordereau.base_cotisation_cg.year - @api.multi def _compute_invoice_count(self): for r in self: r.invoice_count = len(r.invoice_ids) - @api.multi def _compute_liasse_count(self): for r in self: r.liasse_count = len(r.partner_id.liasse_fiscale_ids) - @api.depends('invoice_count', 'invoice_ids.amount_total_signed') - @api.multi + @api.depends("invoice_count", "invoice_ids.amount_total_signed") def _compute_amount_total_cotiz(self): for r in self: - r.amount_total_cotiz = sum( - r.invoice_ids.mapped('amount_total_signed')) + r.amount_total_cotiz = sum(r.invoice_ids.mapped("amount_total_signed")) - @api.depends('invoice_ids', 'invoice_ids.residual_signed') - @api.multi + @api.depends("invoice_ids", "invoice_ids.amount_residual_signed") def _compute_amount_residual(self): for r in self: - r.amount_total_cotiz = sum( - r.invoice_ids.mapped('residual_signed')) + r.amount_total_cotiz = sum(r.invoice_ids.mapped("amount_residual_signed")) - @api.multi def _compute_recipient(self): tag_cotiz_id = self.env.user.company_id.tag_cotiz_id for bordereau in self: child_ids = bordereau.partner_id.child_ids.filtered( - lambda child: - (tag_cotiz_id in child.category_id) and child.email) + lambda child: (tag_cotiz_id in child.category_id) and child.email + ) if bordereau.partner_id.email: bordereau.recipient_ids = bordereau.partner_id + child_ids else: bordereau.recipient_ids = child_ids - @api.multi def _compute_type_assiette(self): for bordereau in self: - bordereau.type_assiette = \ - bordereau.base_cotisation_cg.get_type_assiette( - bordereau.ca, bordereau.va) + bordereau.type_assiette = bordereau.base_cotisation_cg.get_type_assiette( + bordereau.ca, bordereau.va + ) - @api.multi def _search_type_assiette(self, operator, value): - recs = self.search([]).filtered( - lambda r: r.type_assiette == value) + recs = self.search([]).filtered(lambda r: r.type_assiette == value) if recs: - return [('id', 'in', [x.id for x in recs])] + return [("id", "in", [x.id for x in recs])] - @api.multi - def compute_is_sdd(self): - sdd_id = self.env.ref( - 'account_banking_sepa_direct_debit.sepa_direct_debit').id + def _compute_is_sdd(self): + sdd_id = self.env.ref("account_banking_sepa_direct_debit.sepa_direct_debit").id for bdx in self: - if bdx.payment_mode_id and bdx.payment_mode_id.payment_method_id.id == sdd_id: + if ( + bdx.payment_mode_id + and bdx.payment_mode_id.payment_method_id.id == sdd_id + ): bdx.is_sdd = True else: bdx.is_sdd = False - @api.multi def _search_is_sdd(self, operator, value): recs = self.search([]).filtered(lambda x: x.is_sdd is True) if recs: - return [('id', 'in', [x.id for x in recs])] + return [("id", "in", [x.id for x in recs])] - @api.multi def _compute_is_liasse_previ(self): for bordereau in self: - if bordereau.type_liasse_fiscale == 'forecast': + if bordereau.type_liasse_fiscale == "forecast": bordereau.is_liasse_previ = True else: bordereau.is_liasse_previ = False - @api.depends('invoice_ids.residual') - @api.multi + @api.depends("invoice_ids.amount_residual") def _compute_has_outstanding(self): for r in self: if r.invoice_ids: - if r.invoice_ids.filtered(lambda i: i.has_outstanding is True): + if r.invoice_ids.filtered(lambda i: i.invoice_has_outstanding is True): r.has_outstanding = True else: r.has_outstanding = False else: r.has_outstanding = False - @api.multi def _compute_details(self): for r in self: contribs = r.invoice_ids.read_group( - [('id', 'in', r.invoice_ids.ids)], - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + [("id", "in", r.invoice_ids.ids)], + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) detail = "<table class='o_group o_inner_group'>" for contrib in contribs: - detail += ('<tr><td class="o_td_label font-weight-bold">' - + str(contrib.get('type_contribution_id')[1]) - + '</td><td style="width: 100%;">' - + str( - contrib.get('amount_total_signed')) + - ' €</td></tr>') + detail += ( + '<tr><td class="o_td_label font-weight-bold">' + + str(contrib.get("type_contribution_id")[1]) + + '</td><td style="width: 100%;">' + + str(contrib.get("amount_total_signed")) + + " €</td></tr>" + ) detail += "</table><table class='o_group o_inner_group'>" for i in range(1, 5): # Add amount echeance - amount_echeance = round(sum(r.invoice_ids.filtered( - lambda inv: inv.cotiz_quarter == i - ).mapped('amount_total_signed')), 2) - detail += '<tr><td class="o_td_label font-weight-bold">' \ - + 'Trimestre ' + str(i) \ - + '</td><td style="width: 100%;">' \ - + str(amount_echeance) + ' €' + amount_echeance = round( + sum( + r.invoice_ids.filtered( + lambda inv: inv.cotiz_quarter == i + ).mapped("amount_total_signed") + ), + 2, + ) + detail += ( + '<tr><td class="o_td_label font-weight-bold">' + + "Trimestre " + + str(i) + + '</td><td style="width: 100%;">' + + str(amount_echeance) + + " €" + ) # Check if regul has been done after validation - type_contribs = r.invoice_ids.mapped('type_contribution_id') + type_contribs = r.invoice_ids.mapped("type_contribution_id") for type_contrib in type_contribs: - is_exo = len(r.invoice_ids.filtered( - lambda inv: - inv.cotiz_quarter == i and - inv.type_contribution_id == type_contrib - )) > 1 + is_exo = ( + len( + r.invoice_ids.filtered( + lambda inv: inv.cotiz_quarter == i + and inv.type_contribution_id == type_contrib + ) + ) + > 1 + ) if is_exo: - detail += ' ' + '<i class="fa fa-star-o" />' + detail += " " + '<i class="fa fa-star-o" />' break - detail += '</td></tr>' - detail += '</table>' + detail += "</td></tr>" + detail += "</table>" r.details = detail # ------------------------------------------------------ @@ -375,21 +403,27 @@ class Bordereau(models.Model): def validate_cotiz_cg(self): self.ensure_one() for inv in self.invoice_ids: - if inv.state == 'draft': - if not inv.date_invoice: - inv.update({ - 'date_invoice': self.date_cotisation, - }) - inv.update({ - 'payment_mode_id': self.payment_mode_id, - }) + if inv.state == "draft": + if not inv.invoice_date: + inv.update( + { + "invoice_date": self.date_cotisation, + } + ) + inv.update( + { + "payment_mode_id": self.payment_mode_id, + } + ) if self.is_sdd and not inv.mandate_id: raise UserError( - "Vous ne pouvez pas valider une cotisation au " - "prélèvement sans mandat" + _( + "Vous ne pouvez pas valider une cotisation au " + "prélèvement sans mandat" + ) ) else: - inv.action_invoice_open() + inv.action_post() def button_validate_bordereau(self): """ @@ -406,71 +440,69 @@ class Bordereau(models.Model): """ self.ensure_one() # Numéro de séquence - if self.name == 'Brouillon': - self.name = self.env['ir.sequence'].next_by_code('scop.bordereau') + if self.name == "Brouillon": + self.name = self.env["ir.sequence"].next_by_code("scop.bordereau") # Validation des invoices self.validate_cotiz_cg() # Envoi du mail if mail_compose_message_id: - mail_compose_message = self.env['mail.compose.message'].browse( + mail_compose_message = self.env["mail.compose.message"].browse( mail_compose_message_id ) - mail_compose_message.update({ - 'partner_ids': [(6, 0, self.recipient_ids.ids)], - 'res_id': self.id, - }) - mail_compose_message.with_context( - mail_notify_force_send=False - ).send_mail() + mail_compose_message.update( + { + "partner_ids": [(6, 0, self.recipient_ids.ids)], + "res_id": self.id, + } + ) + mail_compose_message.with_context(mail_notify_force_send=False).send_mail() return self.id - @api.multi def validate_bordereau_multi(self, mail_compose_message_id): """ Utilise job queue pour valider les bordereaux """ - batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + - " Validation bordereaux ") - batch = self.env['queue.job.batch'].get_new_batch(batch_name) + batch_name = ( + fields.Datetime.to_string(fields.Datetime.now()) + " Validation bordereaux " + ) + batch = self.env["queue.job.batch"].get_new_batch(batch_name) for bordereau in self: - bordereau.with_context( - job_batch=batch - ).with_delay().validate_bordereau(mail_compose_message_id) + bordereau.with_context(job_batch=batch).with_delay().validate_bordereau( + mail_compose_message_id + ) batch.enqueue() - @api.multi def print_bordereau(self): for bordereau in self: return self.env.ref( - 'cgscop_cotisation_cg.cgscop_bordereau_report'). \ - report_action(bordereau) + "cgscop_cotisation_cg.cgscop_bordereau_report" + ).report_action(bordereau) - @api.multi def action_send_email(self): self.ensure_one() - template_id = self.env.ref( - 'cgscop_cotisation_cg.email_template_cotisation_cg') - ir_model_data = self.env['ir.model.data'] + template_id = self.env.ref("cgscop_cotisation_cg.email_template_cotisation_cg") + ir_model_data = self.env["ir.model.data"] try: compose_form_id = ir_model_data.get_object_reference( - 'mail', 'email_compose_message_wizard_form')[1] + "mail", "email_compose_message_wizard_form" + )[1] except ValueError: compose_form_id = False ctx = { - 'default_model': 'scop.bordereau', - 'default_res_id': self.id, - 'default_use_template': True, - 'default_template_id': template_id.id, + "default_model": "scop.bordereau", + "default_res_id": self.id, + "default_use_template": True, + "default_template_id": template_id.id, } return { - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'mail.compose.message', - 'views': [(compose_form_id, 'form')], - 'view_id': compose_form_id, - 'target': 'new', - 'context': ctx, + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_model": "mail.compose.message", + "views": [(compose_form_id, "form")], + "view_id": compose_form_id, + "target": "new", + "context": ctx, } def update_bordereau_with_liasse(self): @@ -481,39 +513,34 @@ class Bordereau(models.Model): """ self.create_cotiz_and_lines() - @api.multi def open_payment(self): action_context = { - 'company_ids': [self.company_id.id], - 'partner_ids': [ - self.partner_id.commercial_partner_id.id], - 'mode': 'customers' + "company_ids": [self.company_id.id], + "partner_ids": [self.partner_id.commercial_partner_id.id], + "mode": "customers", } return { - 'type': 'ir.actions.client', - 'tag': 'manual_reconciliation_view', - 'context': action_context, + "type": "ir.actions.client", + "tag": "manual_reconciliation_view", + "context": action_context, } def action_show_cotiz(self): """ :return: Ouvre la vue des cotisations liées au bordereau """ - tree_view_id = self.env.ref( - 'cgscop_cotisation.invoice_tree_scop_inherited').id + tree_view_id = self.env.ref("cgscop_cotisation.invoice_tree_scop_inherited").id form_view_id = self.env.ref( - 'cgscop_cotisation_cg.invoice_form_scop_cg_inherited').id + "cgscop_cotisation_cg.invoice_form_scop_cg_inherited" + ).id return { - 'type': 'ir.actions.act_window', - 'name': 'Appels de cotisations', - 'views': [ - [tree_view_id, "tree"], - [form_view_id, "form"] - ], - 'view_mode': 'form', - 'res_model': 'account.invoice', - 'target': 'current', - 'domain': [('id', 'in', self.invoice_ids.ids)], + "type": "ir.actions.act_window", + "name": "Appels de cotisations", + "views": [[tree_view_id, "tree"], [form_view_id, "form"]], + "view_mode": "form", + "res_model": "account.invoice", + "target": "current", + "domain": [("id", "in", self.invoice_ids.ids)], } def action_show_liasse(self): @@ -521,52 +548,51 @@ class Bordereau(models.Model): :return: Ouvre la vue des liasses liées au partenaire """ return { - 'type': 'ir.actions.act_window', - 'name': 'Liasses fiscales - ' + self.partner_id.name, - 'views': [ - [False, "tree"], - [False, "form"] - ], - 'view_mode': 'form', - 'res_model': 'scop.liasse.fiscale', - 'target': 'current', - 'domain': [('partner_id', '=', self.partner_id.id)], + "type": "ir.actions.act_window", + "name": "Liasses fiscales - " + self.partner_id.name, + "views": [[False, "tree"], [False, "form"]], + "view_mode": "form", + "res_model": "scop.liasse.fiscale", + "target": "current", + "domain": [("partner_id", "=", self.partner_id.id)], } def action_change_liasse(self): """ :return: Ouvre le wizard pour changer la liasse """ - wizard = self.env['scop.bordereau.change.liasse.wizard']. \ - create({ - 'bordereau_id': self.id, - }) + wizard = self.env["scop.bordereau.change.liasse.wizard"].create( + { + "bordereau_id": self.id, + } + ) return { - 'type': 'ir.actions.act_window', - 'name': 'Changer la liasse', - 'views': [[False, "form"]], - 'view_mode': 'form', - 'res_model': 'scop.bordereau.change.liasse.wizard', - 'target': 'new', - 'res_id': wizard.id + "type": "ir.actions.act_window", + "name": "Changer la liasse", + "views": [[False, "form"]], + "view_mode": "form", + "res_model": "scop.bordereau.change.liasse.wizard", + "target": "new", + "res_id": wizard.id, } def action_change_payment_mode(self): """ :return: Ouvre le wizard pour changer le mode de paiement """ - wizard = self.env['scop.bordereau.change.payment.mode.wizard']. \ - create({ - 'bordereau_id': self.id, - }) + wizard = self.env["scop.bordereau.change.payment.mode.wizard"].create( + { + "bordereau_id": self.id, + } + ) return { - 'type': 'ir.actions.act_window', - 'name': 'Changer le mode de paiement', - 'views': [[False, "form"]], - 'view_mode': 'form', - 'res_model': 'scop.bordereau.change.payment.mode.wizard', - 'target': 'new', - 'res_id': wizard.id + "type": "ir.actions.act_window", + "name": "Changer le mode de paiement", + "views": [[False, "form"]], + "view_mode": "form", + "res_model": "scop.bordereau.change.payment.mode.wizard", + "target": "new", + "res_id": wizard.id, } def validate_ongoing_bordereau(self): @@ -577,16 +603,20 @@ class Bordereau(models.Model): """ self.ensure_one() ongoing_version = self.check_ongoing_version() - self.write({ - 'name': self.name[0:10] + '-' + str(self.version + 1), - 'version': self.version + 1, - 'date_regul': ongoing_version.date, - 'comment_regul': ongoing_version.comment, - }) + self.write( + { + "name": self.name[0:10] + "-" + str(self.version + 1), + "version": self.version + 1, + "date_regul": ongoing_version.date, + "comment_regul": ongoing_version.comment, + } + ) self.validate_bordereau() - ongoing_version.write({ - 'state': 'validated', - }) + ongoing_version.write( + { + "state": "validated", + } + ) def cancel_ongoing_bordereau(self): """ @@ -595,29 +625,26 @@ class Bordereau(models.Model): - Supprime le versionnage en cours """ self.ensure_one() - self.invoice_ids.filtered( - lambda i: i.state == 'draft' - ).unlink() + self.invoice_ids.filtered(lambda i: i.state == "draft").unlink() ongoing_version = self.check_ongoing_version() - self.write({ - 'liasse_fiscale_id': ongoing_version.liasse_fiscale_id_old.id - }) - self.invoice_ids.update({ - 'liasse_fiscale_id': ongoing_version.liasse_fiscale_id_old.id - }) + self.write({"liasse_fiscale_id": ongoing_version.liasse_fiscale_id_old.id}) + self.invoice_ids.update( + {"liasse_fiscale_id": ongoing_version.liasse_fiscale_id_old.id} + ) ongoing_version.unlink() # ------------------------------------------------------ # Override ORM # ------------------------------------------------------ - @api.multi def unlink(self): - bordereau_not_new = self.filtered(lambda b: b.state != 'new') + bordereau_not_new = self.filtered(lambda b: b.state != "new") if bordereau_not_new: raise UserError( - 'Vous ne pouvez pas passer supprimer un bordereau qui a ' - 'déjà été validé.\n Vous pouvez par contre créer des ' - 'avoirs sur les appels de cotisations.' + _( + "Vous ne pouvez pas passer supprimer un bordereau qui a " + "déjà été validé.\n Vous pouvez par contre créer des " + "avoirs sur les appels de cotisations." + ) ) else: return super(Bordereau, self).unlink() @@ -630,7 +657,6 @@ class Bordereau(models.Model): - Supprime les factures existantes si besoin - Crée les appels de cotisation par trimestre """ - if self.invoice_ids: self.invoice_ids.unlink() @@ -641,104 +667,119 @@ class Bordereau(models.Model): # Invoice cotiz CG # product_cg_id = self.company_id.contribution_cg_id - type_cotisation_cg = self.env.ref('cgscop_partner.riga_14397').id + type_cotisation_cg = self.env.ref("cgscop_partner.riga_14397").id if liasse: - amount_cg = base_cotiz.round_to_closest_multiple( - liasse.contribution_cg, 4) + amount_cg = base_cotiz.round_to_closest_multiple(liasse.contribution_cg, 4) else: - amount_cg = self.env['scop.liasse.fiscale']. \ - get_values_for_cotiz_cg(partner)['plancher1'] + amount_cg = self.env["scop.liasse.fiscale"].get_values_for_cotiz_cg( + partner + )["plancher1"] self.create_contribution( - product_cg_id, type_cotisation_cg, amount_cg + product=product_cg_id, + type_contribution=type_cotisation_cg, + amount=amount_cg, ) - self.env.cr.commit() # Invoice UR et Fédé - type_cotisation_ur = self.env.ref('cgscop_partner.riga_14399').id - journal_ur_or_fede = self.company_id.contribution_ur_or_fede_journal_id + type_cotisation_ur = self.env.ref("cgscop_partner.riga_14399").id # Invoice cotiz Fede Com # if partner.is_federation_com: product_fede_com_id = self.company_id.contribution_fede_com_id - account_id = self.company_id.receivable_account_fede_com_id - type_cotisation_fede_com = self.env.ref( - 'cgscop_partner.riga_14398').id + journal_fede_com_id = self.company_id.journal_fede_com_id + type_cotisation_fede_com = self.env.ref("cgscop_partner.riga_14398").id if liasse: amount_fede_com = base_cotiz.round_to_closest_multiple( - liasse.contribution_com, 4) + liasse.contribution_com, 4 + ) else: - amount_fede_com = self.env['scop.liasse.fiscale']. \ - get_plancher_cotiz()['fede_com'] + amount_fede_com = self.env["scop.liasse.fiscale"].get_plancher_cotiz()[ + "fede_com" + ] self.create_contribution( - product_fede_com_id, type_cotisation_fede_com, amount_fede_com, - journal_ur_or_fede, account_id + product=product_fede_com_id, + type_contribution=type_cotisation_fede_com, + amount=amount_fede_com, + journal_id=journal_fede_com_id, ) - self.env.cr.commit() # Invoice cotiz Fede CAE # if partner.cae: product_fede_cae_id = self.company_id.contribution_fede_cae_id - account_id = self.company_id.receivable_account_fede_cae_id - type_cotisation_fede_cae = self.env.ref( - 'cgscop_partner.cotiz_fede_cae').id + journal_fede_cae_id = self.company_id.journal_fede_cae_id + type_cotisation_fede_cae = self.env.ref("cgscop_partner.cotiz_fede_cae").id if liasse: amount_fede_cae = base_cotiz.round_to_closest_multiple( - liasse.contribution_cae, 4) + liasse.contribution_cae, 4 + ) else: - amount_fede_cae = self.env['scop.liasse.fiscale']. \ - get_plancher_cotiz()['fede_cae'] + amount_fede_cae = self.env["scop.liasse.fiscale"].get_plancher_cotiz()[ + "fede_cae" + ] self.create_contribution( - product_fede_cae_id, type_cotisation_fede_cae, amount_fede_cae, - journal_ur_or_fede, account_id + product=product_fede_cae_id, + type_contribution=type_cotisation_fede_cae, + amount=amount_fede_cae, + journal_id=journal_fede_cae_id, ) - self.env.cr.commit() # Invoice cotiz UR HDF # - ur_hdf = self.env.ref('cgscop_partner.riga_14232').id + ur_hdf = self.env.ref("cgscop_partner.riga_14232").id if partner.ur_id.id == ur_hdf: product_hdf_id = self.company_id.contribution_hdf_id - account_id = self.company_id.receivable_account_ur_hdf_id + journal_hdf_id = self.company_id.journal_ur_hdf_id if liasse: amount_hdf = base_cotiz.round_to_closest_multiple( - liasse.contribution_hdf, 4) + liasse.contribution_hdf, 4 + ) else: - amount_hdf = self.env['scop.liasse.fiscale']. \ - get_plancher_cotiz()['ur_hdf'] + amount_hdf = self.env["scop.liasse.fiscale"].get_plancher_cotiz()[ + "ur_hdf" + ] self.create_contribution( - product_hdf_id, type_cotisation_ur, amount_hdf, - journal_ur_or_fede, account_id + product=product_hdf_id, + type_contribution=type_cotisation_ur, + amount=amount_hdf, + journal_id=journal_hdf_id, ) - self.env.cr.commit() # Invoice cotiz UR Med # - ur_med = self.env.ref('cgscop_partner.riga_14243').id + ur_med = self.env.ref("cgscop_partner.riga_14243").id if partner.ur_id.id == ur_med: product_med_id = self.company_id.contribution_med_id - account_id = self.company_id.receivable_account_ur_med_id + journal_ur_med_id = self.company_id.journal_ur_med_id if liasse: amount_med = base_cotiz.round_to_closest_multiple( - liasse.contribution_med, 4) + liasse.contribution_med, 4 + ) else: - amount_med = self.env['scop.liasse.fiscale']. \ - get_plancher_cotiz()['ur_med'] + amount_med = self.env["scop.liasse.fiscale"].get_plancher_cotiz()[ + "ur_med" + ] self.create_contribution( - product_med_id, type_cotisation_ur, amount_med, - journal_ur_or_fede, account_id + product=product_med_id, + type_contribution=type_cotisation_ur, + amount=amount_med, + journal_id=journal_ur_med_id, ) - self.env.cr.commit() def create_contribution( - self, product, type_contribution, amount=0, - journal_id=False, account_id=False, type_invoice='out_invoice'): + self, + product, + type_contribution, + amount=0, + journal_id=False, + type_invoice="out_invoice", + ): """ Create invoice from Contribution Base :param product: product_id @@ -749,100 +790,117 @@ class Bordereau(models.Model): :param type_invoice: invoice or refund :return: invoice """ - Invoice = self.env['account.invoice'] - InvoiceLine = self.env['account.invoice.line'] + Invoice = self.env["account.move"] partner = self.partner_id liasse = self.liasse_fiscale_id base_cotiz = self.base_cotisation_cg - quarters = [base_cotiz.trimester_1, base_cotiz.trimester_2, - base_cotiz.trimester_3, base_cotiz.trimester_4] - type_contrib_name = self.env['scop.contribution.type'].browse( - type_contribution).name + quarters = [ + base_cotiz.trimester_1, + base_cotiz.trimester_2, + base_cotiz.trimester_3, + base_cotiz.trimester_4, + ] + type_contrib_name = ( + self.env["scop.contribution.type"].browse(type_contribution).name + ) # TODO: Specific CAE calculation : to be deleted when 2022 is generated - type_contrib_cae = self.env.ref('cgscop_partner.cotiz_fede_cae').id - if type_contribution == type_contrib_cae and self.year == '2022': + type_contrib_cae = self.env.ref("cgscop_partner.cotiz_fede_cae").id + if type_contribution == type_contrib_cae and self.year == "2022": amount = ((amount / 4) * 3) + 25 # ... End specific CAE 2022 - for i in range(1, self.nb_quarter + 1): - cotiz_quarter = (4 - self.nb_quarter) + i - - journal_id = self.company_id.contribution_journal_id \ - if not journal_id else journal_id - account_id = partner.property_account_receivable_id \ - if not account_id else account_id - member_invoice = Invoice.create({ - 'partner_id': partner.id, - 'liasse_fiscale_id': liasse.id, - 'type': type_invoice, - 'year': self.year, - 'is_contribution': True, - 'type_contribution_id': type_contribution, - 'name': 'T' + str(cotiz_quarter) + ' ' + self.year + - ' - ' + type_contrib_name, - 'journal_id': journal_id.id, - 'state': 'draft', - 'account_id': account_id.id, - 'payment_mode_id': partner.customer_payment_mode_id.id, - 'date_invoice': self.date_cotisation, - 'date_due': quarters[cotiz_quarter - 1], - 'bordereau_id': self.id, - 'amount_cg_calculated': amount, - 'cotiz_quarter': cotiz_quarter, - }) - - # Création de la ligne de cotisation - price_unit = amount / 4 + for i in range(1, int(self.nb_quarter) + 1): + cotiz_quarter = (4 - int(self.nb_quarter)) + i + journal_id = ( + self.company_id.contribution_journal_id + if not journal_id + else journal_id + ) + # Calcul prix + price_unit = amount / 4 # TODO: Specific CAE calculation : to be deleted when 2022 is generated - if type_contribution == type_contrib_cae and self.year == '2022': + if type_contribution == type_contrib_cae and self.year == "2022": if cotiz_quarter == 1: price_unit = 25 else: price_unit = (amount - 25) / 3 # ... End specific CAE 2022 - InvoiceLine.create({ - 'invoice_id': member_invoice.id, - 'product_id': product.id, - 'account_id': product.property_account_income_id.id, - 'invoice_line_tax_ids': [(6, 0, product.taxes_id.ids)], - 'name': product.name + " T" + str(cotiz_quarter), - 'price_unit': price_unit - }) + Invoice.create( + { + "partner_id": partner.id, + "liasse_fiscale_id": liasse.id, + "move_type": type_invoice, + "year": self.year, + "is_contribution": True, + "type_contribution_id": type_contribution, + "ref": ( + "T" + + str(cotiz_quarter) + + " " + + self.year + + " - " + + type_contrib_name + ), + "journal_id": journal_id.id, + "state": "draft", + "payment_mode_id": partner.customer_payment_mode_id.id, + "invoice_date": self.date_cotisation, + "invoice_date_due": quarters[cotiz_quarter - 1], + "bordereau_id": self.id, + "amount_cg_calculated": amount, + "cotiz_quarter": str(cotiz_quarter), + "invoice_line_ids": [ + ( + 0, + None, + { + "product_id": product.id, + "account_id": product.property_account_income_id.id, + "tax_ids": [(6, 0, product.taxes_id.ids)], + "name": product.name + " T" + str(cotiz_quarter), + "price_unit": price_unit, + "price_subtotal": price_unit, + }, + ), + ], + } + ) def check_ongoing_version(self): """ :return: le versionnage en cours """ ongoing_version = self.bordereau_version_ids.filtered( - lambda v: v.version == self.version and v.state == 'new' + lambda v: v.version == self.version and v.state == "new" ) if len(ongoing_version) != 1: - raise ValueError('Erreur sur le versionnage de ce bordereau') + raise ValueError(_("Erreur sur le versionnage de ce bordereau")) else: return ongoing_version - @api.multi def get_bordereau_move_line(self): """ Get move line for invoices in bordereau :return: dict with date as key and amount (float) as value """ - MoveLine = self.env['account.move.line'] + # TODO: voir si possible d'optimiser avec le nouveau modèle + MoveLine = self.env["account.move.line"] for bordereau in self: inv_ids = bordereau.invoice_ids if bordereau.is_regul: - inv_ids = inv_ids.filtered( - lambda i: i.type == 'out_invoice') - move_lines = MoveLine.search([ - ('invoice_id', 'in', inv_ids.ids), - ('account_id.internal_type', '=', 'receivable')], - order='date_maturity', + inv_ids = inv_ids.filtered(lambda i: i.move_type == "out_invoice") + move_lines = MoveLine.search( + [ + ("move_id", "in", inv_ids.ids), + ("account_id.internal_type", "=", "receivable"), + ], + order="date_maturity", ) - schedule = list(dict.fromkeys(move_lines.mapped('date_maturity'))) + schedule = list(dict.fromkeys(move_lines.mapped("date_maturity"))) schedule.sort() schedule_plan = [] for date in schedule: @@ -850,39 +908,43 @@ class Bordereau(models.Model): for item in move_lines: if item.date_maturity == date: amount += item.debit - item.credit - schedule_plan.append({ - 'date': date.strftime('%d/%m/%Y'), - 'amount': amount, - }) + schedule_plan.append( + { + "date": date.strftime("%d/%m/%Y"), + "amount": amount, + } + ) return schedule_plan - @api.multi def get_bordereau_move_line_with_payments(self): """ Get payment dates for invoices in bordereau :return: dict with date as key and amount (float) as value """ - MoveLine = self.env['account.move.line'] + # TODO: voir si possible d'optimiser avec le nouveau modèle + MoveLine = self.env["account.move.line"] for bordereau in self: inv_ids = bordereau.invoice_ids.ids schedule_plan = MoveLine.read_group( - [('invoice_id', 'in', inv_ids), - ('account_id.internal_type', '=', 'receivable')], - fields=['date_maturity', 'credit', 'debit', 'amount_residual'], - groupby=['date_maturity:day'], - orderby='date_maturity', - lazy=False + [ + ("move_id", "in", inv_ids), + ("account_id.internal_type", "=", "receivable"), + ], + fields=["date_maturity", "credit", "debit", "amount_residual"], + groupby=["date_maturity:day"], + orderby="date_maturity", + lazy=False, + ) + total_amount = sum(list(map(lambda l: l.get("debit"), schedule_plan))) + total_residual = sum( + list(map(lambda l: l.get("amount_residual"), schedule_plan)) ) - total_amount = sum(list(map( - lambda l: l.get('debit'), schedule_plan))) - total_residual = sum(list(map( - lambda l: l.get('amount_residual'), schedule_plan))) total_paid = total_amount - total_residual return { - 'plan': schedule_plan, - 'total_amount': total_amount, - 'total_paid': total_paid, - 'total_residual': total_residual + "plan": schedule_plan, + "total_amount": total_amount, + "total_paid": total_paid, + "total_residual": total_residual, } def get_contribution_type(self): @@ -890,13 +952,14 @@ class Bordereau(models.Model): Get contribution by type :return: dict type_contribution and amount """ - domain = [('id', 'in', self.invoice_ids.ids)] + domain = [("id", "in", self.invoice_ids.ids)] if self.is_regul: - domain.append(('type', '=', 'out_invoice')) + domain.append(("move_type", "=", "out_invoice")) return self.invoice_ids.read_group( domain, - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) def get_contribution_type_refund(self): """ @@ -904,11 +967,12 @@ class Bordereau(models.Model): :return: dict type_contribution and amount """ return self.invoice_ids.read_group( - [('id', 'in', self.invoice_ids.ids), ('type', '=', 'out_refund')], - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + [("id", "in", self.invoice_ids.ids), ("move_type", "=", "out_refund")], + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) # Email def get_recipients(self): - recipients = ','.join(map(lambda x: str(x), self.recipient_ids.ids)) + recipients = ",".join(map(lambda x: str(x), self.recipient_ids.ids)) return recipients diff --git a/models/scop_bordereau_cg_version.py b/models/scop_bordereau_cg_version.py index ef5e3217445f0f93c3314280e4383a49a91914e5..1ba4d093272b037dfeeb0d8be5131be472eb8130 100644 --- a/models/scop_bordereau_cg_version.py +++ b/models/scop_bordereau_cg_version.py @@ -1,58 +1,70 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from datetime import timedelta -from odoo import fields, models, api +from odoo import _, api, fields, models from odoo.exceptions import ValidationError class BordereauVersion(models.Model): - _name = 'scop.bordereau.version' - _description = 'Historique des versions des bordereaux des cotisations CG' + _name = "scop.bordereau.version" + _description = "Historique des versions des bordereaux des cotisations CG" bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau de rattachement', + comodel_name="scop.bordereau", + string="Bordereau de rattachement", required=True, readonly=True, - ondelete='cascade') - version = fields.Integer('Version du bordereau', readonly=True) - comment = fields.Char(string='Motif') + ondelete="cascade", + ) + version = fields.Integer("Version du bordereau", readonly=True) + comment = fields.Char(string="Motif") liasse_fiscale_id_old = fields.Many2one( - comodel_name='scop.liasse.fiscale', - string='Ancienne liasse fiscale', - ondelete='set null', - readonly=True + comodel_name="scop.liasse.fiscale", + string="Ancienne liasse fiscale", + ondelete="set null", + readonly=True, ) type_assiette = fields.Selection( - string='Ancien type d\'assiette', - selection=[('ca', 'CA'), - ('va', 'VA'), ], - readonly=True) - date = fields.Date('Date', readonly=True) - montant_assiette = fields.Integer( - string='Ancien montant assiette', readonly=True) - company_currency_id = fields.Many2one( - related='bordereau_id.company_currency_id') + string="Ancien type d'assiette", + selection=[ + ("ca", "CA"), + ("va", "VA"), + ], + readonly=True, + ) + date = fields.Date("Date", readonly=True) + montant_assiette = fields.Integer(string="Ancien montant assiette", readonly=True) + company_currency_id = fields.Many2one(related="bordereau_id.company_currency_id") amount_total_cotiz = fields.Monetary( - string='Ancien montant cotisation', - currency_field='company_currency_id', readonly=True) - state = fields.Selection([ - ('new', 'Brouillon'), - ('validated', 'Validée')], + string="Ancien montant cotisation", + currency_field="company_currency_id", + readonly=True, + ) + state = fields.Selection( + [("new", "Brouillon"), ("validated", "Validée")], string="Statut", - default='new', readonly=True) + default="new", + readonly=True, + ) # ------------------------------------------------------ # Constrain Functions # ------------------------------------------------------ - @api.constrains('state') + @api.constrains("state") def check_unique_state_new(self): - """ Une seule version en brouillon par bordereau """ - if len(self.bordereau_id.bordereau_version_ids.filtered( - lambda v: v.state == 'new' - )) > 1: + """Une seule version en brouillon par bordereau""" + if ( + len( + self.bordereau_id.bordereau_version_ids.filtered( + lambda v: v.state == "new" + ) + ) + > 1 + ): raise ValidationError( - 'Vous devez valider ou annuler les versions de bordereaux en ' - 'cours de modification avant de créer une nouvelle version !') + _( + "Vous devez valider ou annuler les versions de bordereaux en " + "cours de modification avant de créer une nouvelle version !" + ) + ) diff --git a/models/scop_cotisation_cg.py b/models/scop_cotisation_cg.py index 64b10fb9d4313188c11c0e9dd2946568013ff8c8..9c525965973d958ff6cb967a1097eae96bb39215 100644 --- a/models/scop_cotisation_cg.py +++ b/models/scop_cotisation_cg.py @@ -4,11 +4,12 @@ import base64 import json import logging -import xlsxwriter -from io import BytesIO from datetime import datetime +from io import BytesIO -from odoo import models, fields, api, exceptions +import xlsxwriter + +from odoo import _, api, exceptions, fields, models _logger = logging.getLogger(__name__) @@ -18,61 +19,62 @@ class ScopCotisation(models.Model): _name = "scop.cotisation.cg" _description = "Base des cotisations CG" - name = fields.Char( - string='Nom', - compute='_compute_name', - store=True) + name = fields.Char(string="Nom", compute="_compute_name", store=True) simul_ids = fields.One2many( - comodel_name='scop.cotisation.cg.simulation', - inverse_name='cotisation_id', - string='Simulations') + comodel_name="scop.cotisation.cg.simulation", + inverse_name="cotisation_id", + string="Simulations", + ) invoice_ids = fields.One2many( - comodel_name='account.invoice', - inverse_name='cotisation_cg_id', - string='Factures', + comodel_name="account.move", + inverse_name="cotisation_cg_id", + string="Factures", domain=[ - ('type', 'in', ('out_invoice', 'out_refund')), - ('is_contribution', '=', True) - ]) + ("move_type", "in", ("out_invoice", "out_refund")), + ("is_contribution", "=", True), + ], + ) bordereau_ids = fields.One2many( - comodel_name='scop.bordereau', - inverse_name='base_cotisation_cg', - string='Bordereau', ) - - state = fields.Selection([ - ('new', 'Brouillon'), - ('ongoing', 'En cours'), - ('end', 'Clôturé')], - string="Statut", default='new', - compute='_compute_state', - store=True, track_visibility='onchange', ) + comodel_name="scop.bordereau", + inverse_name="base_cotisation_cg", + string="Bordereau", + ) + + state = fields.Selection( + [("new", "Brouillon"), ("ongoing", "En cours"), ("end", "Clôturé")], + string="Statut", + default="new", + compute="_compute_state", + store=True, + ) invoice_count = fields.Integer( - string='Appels de cotisations émis', - compute='_compute_real') + string="Appels de cotisations émis", compute="_compute_real" + ) invoice_valid_count = fields.Integer( - string='Appels de cotisations validés', - compute='_compute_real') + string="Appels de cotisations validés", compute="_compute_real" + ) amount_called = fields.Monetary( - 'Montant appelé', - compute='_compute_amount_called', - currency_field='company_currency_id') + "Montant appelé", + compute="_compute_amount_called", + currency_field="company_currency_id", + ) amount_residual = fields.Monetary( - 'Montant restant à réglé', - compute='_compute_amount_residual', - currency_field='company_currency_id') + "Montant restant à réglé", + compute="_compute_amount_residual", + currency_field="company_currency_id", + ) amount_paid = fields.Monetary( - 'Montant payé', - compute='_compute_amount_paid', - currency_field='company_currency_id') + "Montant payé", + compute="_compute_amount_paid", + currency_field="company_currency_id", + ) - percent_cotiz_paid = fields.Float( - "% Payées", - compute="_compute_percent_cotiz_paid") + percent_cotiz_paid = fields.Float("% Payées", compute="_compute_percent_cotiz_paid") graph_values = fields.Text(compute="_compute_graph_values") @@ -81,44 +83,46 @@ class ScopCotisation(models.Model): # ------------------------------------------------------ # Unicité d'année' (company - année) _sql_constraints = [ - ('contribution_unique', - 'unique(year, company_id)', - "La gestion des cotisations pour cette année existe déjà"), + ( + "contribution_unique", + "unique(year, company_id)", + "La gestion des cotisations pour cette année existe déjà", + ), ] # ------------------------------------------------------ # Compute fields # ------------------------------------------------------ - @api.depends('year', 'state') - @api.multi + @api.depends("year", "state") def _compute_name(self): for cotiz in self: - cotiz.name = "Cotisations %d - %s" % ( + cotiz.name = "Cotisations %s - %s" % ( cotiz.year, - dict(self._fields['state'].selection).get(cotiz.state)) + dict(self._fields["state"].selection).get(cotiz.state), + ) - @api.multi def _compute_amount_called(self): for cotiz in self: - cotiz.amount_called = sum(cotiz.invoice_ids.filtered( - lambda i: i.state != 'draft').mapped("amount_total")) + cotiz.amount_called = sum( + cotiz.invoice_ids.filtered(lambda i: i.state == "posted").mapped( + "amount_total_signed" + ) + ) - @api.multi def _compute_amount_residual(self): for cotiz in self: cotiz.amount_residual = sum( - cotiz.invoice_ids.mapped("residual_signed")) + cotiz.invoice_ids.mapped("amount_residual_signed") + ) - @api.multi def _compute_amount_paid(self): """ montant déjà payé = différence entre le reste à payer du total validé, le reste à payer étant égal à 0 pour les factures en brouillon - """ + """ for cotiz in self: cotiz.amount_paid = cotiz.amount_called - cotiz.amount_residual - @api.multi def _compute_percent_cotiz_paid(self): for cotiz in self: if cotiz.amount_called != 0: @@ -133,48 +137,59 @@ class ScopCotisation(models.Model): cotiz.percent_cotiz_paid = 0 @api.depends( - 'invoice_ids', - 'invoice_ids.state', - 'invoice_ids.amount_total', + "invoice_ids", + "invoice_ids.state", + "invoice_ids.amount_total_signed", ) - @api.multi def _compute_real(self): for cotiz in self: cotiz.invoice_count = len(cotiz.invoice_ids) - cotiz.invoice_valid_count = len(cotiz.invoice_ids.filtered( - lambda i: i.state in ('open', 'paid'))) + cotiz.invoice_valid_count = len( + cotiz.invoice_ids.filtered(lambda i: i.state == "posted") + ) - @api.multi def _compute_graph_values(self): for cotiz in self: - draft_count = len(cotiz.invoice_ids.filtered( - lambda i: i.state == 'draft')) - opened_count = len(cotiz.invoice_ids.filtered( - lambda i: i.state == 'open')) - paid_count = len(cotiz.invoice_ids.filtered( - lambda i: i.state == 'paid')) - cotiz.graph_values = json.dumps([{ - 'values': [ - {'label': 'Brouillons', 'value': draft_count}, - {'label': 'Ouverts', 'value': opened_count}, - {'label': 'Payés', 'value': paid_count}, - ], - 'area': True, - 'title': '', - 'key': 'Cotisations', - }]) + draft_count = len(cotiz.invoice_ids.filtered(lambda i: i.state == "draft")) + opened_count = len( + cotiz.invoice_ids.filtered( + lambda i: i.state == "posted" + and i.payment_state not in ("paid", "reversed") + ) + ) + paid_count = len( + cotiz.invoice_ids.filtered( + lambda i: i.state == "posted" and i.payment_state == "paid" + ) + ) + cotiz.graph_values = json.dumps( + [ + { + "values": [ + {"label": "Brouillons", "value": draft_count}, + {"label": "Ouverts", "value": opened_count}, + {"label": "Payés", "value": paid_count}, + ], + "area": True, + "title": "", + "key": "Cotisations", + } + ] + ) - @api.depends('invoice_ids', 'invoice_ids.state') + @api.depends("invoice_ids", "invoice_ids.state") def _compute_state(self): for cotiz in self: - if len(cotiz.invoice_ids) == 0 and cotiz.state != 'new': - cotiz.state = 'new' - elif len(cotiz.invoice_ids) == len(cotiz.invoice_ids.filtered( - lambda i: i.state in ('paid', 'cancel'))) \ - and cotiz.state != 'end': - cotiz.state = 'end' - elif cotiz.state != 'ongoing': - cotiz.state = 'ongoing' + if len(cotiz.invoice_ids) == 0: + cotiz.state = "new" + elif ( + len(cotiz.invoice_ids) + == len(cotiz.invoice_ids.filtered(lambda i: i.state == "posted")) + and cotiz.state != "end" + ): + cotiz.state = "end" + elif cotiz.state != "ongoing": + cotiz.state = "ongoing" # ------------------------------------------------------ # Button functions @@ -183,138 +198,181 @@ class ScopCotisation(models.Model): """ Open wizard to generate cotisations for renew members """ - if not self.env.user.company_id.is_contribution_cg: + if not self.env.company.is_contribution_cg: + raise exceptions.UserError(_("La cotisation CG Scop n'est pas configurée.")) + + if ( + not self.trimester_1 + or not self.trimester_2 + or not self.trimester_3 + or not self.trimester_4 + ): raise exceptions.UserError( - "La cotisation CG Scop n'est pas configurée.") - - if not self.trimester_1 or not self.trimester_2 or not self.trimester_3 or not self.trimester_4: - raise exceptions.UserError( - "Les trimestres doivent être configurés pour lancer les cotisations.") + _("Les trimestres doivent être configurés pour lancer les cotisations.") + ) if not self.date_cotisation: raise exceptions.UserError( - "La date de calcul des cotisations doit être renseignée pour lancer les cotisations.") + _( + "La date de calcul des cotisations doit être renseignée pour " + "lancer les cotisations." + ) + ) # List of members already invoiced - member_invoiced = self.invoice_ids.mapped('partner_id') + member_invoiced = self.invoice_ids.mapped("partner_id") # List of members members = self.get_members() # List of not invoiced members - members_to_invoice = (members - member_invoiced) + members_to_invoice = members - member_invoiced if len(members_to_invoice) > 0: message = ( - "<h3>Appels de cotisation " + str(self.year) + - "</h3> <hr/>" + - "Nombre d'adhérents renouvelés : " + - str(self.member_count) + - "<br/>Bordereaux déjà générées non vides : " + - str(self.invoiced_member_count) + - "<br/>Bordereaux à générer : " + - str(len(members_to_invoice)) + - "<p>Les appels de cotisation vont être générés.</p> " + "<h3>Appels de cotisation " + + self.year + + "</h3> <hr/>" + + "Nombre d'adhérents renouvelés : " + + str(self.member_count) + + "<br/>Bordereaux déjà générées non vides : " + + str(self.invoiced_member_count) + + "<br/>Bordereaux à générer : " + + str(len(members_to_invoice)) + + "<p>Les appels de cotisation vont être générés.</p> " ) - message_id = self.env['message.wizard'].create({ - 'message': message, - 'cancel_button': True, - 'action': 'action_cotiz_generate(' - + str(members_to_invoice.ids) + ')', - }) + return { + "type": "ir.actions.act_window.message", + "title": _("Génération des appels de cotisation annuels"), + "is_html_message": True, + "message": _(message), + "close_button_title": False, + "buttons": [ + { + "type": "method", + "name": "Lancer le calcul", + "model": self._name, + "method": "action_cotiz_generate", + "args": [self.id, members_to_invoice.ids], + "classes": "btn-primary", + }, + { + "type": "ir.actions.act_window_close", + "name": "Fermer", + }, + ], + } else: - message = ("<p class='text-center'>Tous les appels de " + - "cotisations annuels ont déjà été créés !</p>") - message_id = self.env['message.wizard'].create( - {'message': message}) - - return { - 'name': 'Génération des appels de cotisation annuels', - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'message.wizard', - 'res_id': message_id.id, - 'target': 'new' - } + message = ( + "<p class='text-center'>Tous les appels de " + + "cotisations annuels ont déjà été créés !</p>" + ) + return { + "type": "ir.actions.act_window.message", + "title": _("Génération des appels de cotisation annuels"), + "is_html_message": True, + "message": _(message), + "close_button_title": False, + "buttons": [ + { + "type": "ir.actions.act_window_close", + "name": "Fermer", + }, + ], + } - def action_cotiz_generate(self, *ids): + def action_cotiz_generate(self, member_ids): """ - Function to be used by message.wizard in "ok" action + Create contribution for members + :params member_ids: list of member ids """ - members_to_invoice = self.env['res.partner'].browse(*ids) - + member_to_invoice = self.env["res.partner"].browse(member_ids) # Job queue - batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + - " Génération des bordereaux " + str(self.year)) - batch = self.env['queue.job.batch'].get_new_batch(batch_name) - for member in members_to_invoice: + batch_name = ( + fields.Datetime.to_string(fields.Datetime.now()) + + " Génération des bordereaux " + + self.year + ) + batch = self.env["queue.job.batch"].get_new_batch(batch_name) + for member in member_to_invoice: liasse_id = self.get_liasse(member) - self.with_context( - job_batch=batch - ).with_delay().create_bordereau( - member=member, liasse=liasse_id, - nb_quarter=4, date=False) + self.with_context(job_batch=batch).with_delay().create_bordereau( + member=member, liasse=liasse_id, nb_quarter="4", date=False + ) batch.enqueue() def cotiz_generate_wizard(self): """ Open wizard to generate cotisations for new members """ - if not self.trimester_1 or not self.trimester_2 or not self.trimester_3 or not self.trimester_4: + if ( + not self.trimester_1 + or not self.trimester_2 + or not self.trimester_3 + or not self.trimester_4 + ): raise exceptions.UserError( - "Les trimestres doivent être configurés pour lancer les cotisations.") + _("Les trimestres doivent être configurés pour lancer les cotisations.") + ) if not self.date_cotisation: raise exceptions.UserError( - "La date de calcul des cotisations doit être renseignée pour lancer les cotisations.") + _( + "La date de calcul des cotisations doit être renseignée pour lancer " + "les cotisations." + ) + ) - wizard = self.env['scop.cotisation.cg.wizard'].create({ - 'year': self.year, - 'cotisation_cg_id': self.id, - }) + wizard = self.env["scop.cotisation.cg.wizard"].create( + { + "year": self.year, + "cotisation_cg_id": self.id, + } + ) return { - 'name': 'Génération des appels de cotisation nouveaux adhérents', - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'scop.cotisation.cg.wizard', - 'res_id': wizard.id, - 'context': { - 'id_cotisation_cg': self.id, + "name": "Génération des appels de cotisation nouveaux adhérents", + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_model": "scop.cotisation.cg.wizard", + "res_id": wizard.id, + "context": { + "id_cotisation_cg": self.id, }, - 'target': 'new' + "target": "new", } def cotiz_view(self): """ Button to open view for Appels de cotisations """ - tree_id = self.env.ref( - 'cgscop_cotisation.invoice_tree_scop_inherited').id - form_id = self.env.ref( - 'cgscop_cotisation_cg.invoice_form_scop_cg_inherited').id - search_id = (self.env.ref( - 'cgscop_cotisation_cg.invoice_search_scop_cg_inherited').id, - 'view_account_invoice_cotiz_cg_search') + tree_id = self.env.ref("cgscop_cotisation.invoice_tree_scop_inherited").id + form_id = self.env.ref("cgscop_cotisation_cg.invoice_form_scop_cg_inherited").id + search_id = ( + self.env.ref("cgscop_cotisation_cg.invoice_search_scop_cg_inherited").id, + "view_account_invoice_cotiz_cg_search", + ) return { - 'name': "Appels de cotisation " + str(self.year), - 'type': 'ir.actions.act_window', - 'res_model': 'account.invoice', - 'view_mode': 'tree,form', - 'view_type': 'form', - 'search_view_id': search_id, - 'views': [ - [tree_id, 'tree'], [form_id, 'form'], - [False, 'pivot'], [False, 'graph'] + "name": "Appels de cotisation " + self.year, + "type": "ir.actions.act_window", + "res_model": "account.invoice", + "view_mode": "tree,form", + "view_type": "form", + "search_view_id": search_id, + "views": [ + [tree_id, "tree"], + [form_id, "form"], + [False, "pivot"], + [False, "graph"], ], - 'domain': [('cotisation_cg_id', '=', self.id)], - 'context': { - 'create': False, - 'default_year': self.year, - 'default_is_contribution': True, - 'default_cotisation_cg_id': self.id + "domain": [("cotisation_cg_id", "=", self.id)], + "context": { + "create": False, + "default_year": self.year, + "default_is_contribution": True, + "default_cotisation_cg_id": self.id, }, - 'target': 'current', + "target": "current", } def bordereaux_view(self): @@ -322,13 +380,13 @@ class ScopCotisation(models.Model): Button to open view for Bordereaux """ return { - 'name': "Bordereaux de cotisation " + str(self.year), - 'type': 'ir.actions.act_window', - 'res_model': 'scop.bordereau', - 'view_mode': 'tree,form', - 'view_type': 'form', - 'domain': [('base_cotisation_cg', '=', self.id)], - 'target': 'current', + "name": "Bordereaux de cotisation " + self.year, + "type": "ir.actions.act_window", + "res_model": "scop.bordereau", + "view_mode": "tree,form", + "view_type": "form", + "domain": [("base_cotisation_cg", "=", self.id)], + "target": "current", } def create_bordereau(self, member, nb_quarter, liasse=None, date=False): @@ -352,18 +410,20 @@ class ScopCotisation(models.Model): staff_average = 0 date_invoice = date if date else self.date_cotisation - bordereau = self.env['scop.bordereau'].create({ - 'partner_id': member.id, - 'payment_mode_id': member.customer_payment_mode_id.id, - 'base_cotisation_cg': self.id, - 'liasse_fiscale_id': liasse.id if liasse else None, - 'year_liasse': liasse.year if liasse else 0, - 'date_cotisation': date_invoice, - 'nb_quarter': nb_quarter, - 'staff_count': staff_count, - 'staff_shareholder_count': staff_shareholder_count, - 'staff_average': staff_average, - }) + bordereau = self.env["scop.bordereau"].create( + { + "partner_id": member.id, + "payment_mode_id": member.customer_payment_mode_id.id, + "base_cotisation_cg": self.id, + "liasse_fiscale_id": liasse.id if liasse else None, + "year_liasse": liasse.year if liasse else 0, + "date_cotisation": date_invoice, + "nb_quarter": nb_quarter, + "staff_count": staff_count, + "staff_shareholder_count": staff_shareholder_count, + "staff_average": staff_average, + } + ) bordereau.create_cotiz_and_lines() return bordereau.id @@ -371,29 +431,27 @@ class ScopCotisation(models.Model): """ Open wizard to validate all bordereaux from "base de cotisation" """ - bordereau_to_validate = self.bordereau_ids.filtered( - lambda b: b.state == 'new' - ) + bordereau_to_validate = self.bordereau_ids.filtered(lambda b: b.state == "new") bordereau_to_validate.validate_bordereau_multi() if len(bordereau_to_validate) > 0: - message = ( - "%s bordereaux sont en cours de validation" % - len(bordereau_to_validate) + message = "%s bordereaux sont en cours de validation" % len( + bordereau_to_validate ) else: - message = ( - "Tous les bordereaux ont déjà été validés" - ) - message_id = self.env['message.wizard'].create( - {'message': message}) + message = "Tous les bordereaux ont déjà été validés" return { - 'name': 'Validation des bordereaux', - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'message.wizard', - 'res_id': message_id.id, - 'target': 'new' + "type": "ir.actions.act_window.message", + "title": _("Validation des bordereaux"), + "is_html_message": True, + "message": _(message), + "close_button_title": False, + "buttons": [ + { + "type": "ir.actions.act_window_close", + "name": "Fermer", + }, + ], } def add_simul(self): @@ -405,13 +463,13 @@ class ScopCotisation(models.Model): @return: object scop.cotisation.cg.simulation """ # Get context - type_simul = self.env.context.get('type_simul') + type_simul = self.env.context.get("type_simul") # Get contribution type - type_cotisation_cg = self.env.ref('cgscop_partner.riga_14397') + type_cotisation_cg = self.env.ref("cgscop_partner.riga_14397") # Get product type - InvoiceLine = self.env['account.invoice.line'] + AccountMoveLine = self.env["account.move.line"] product_cg_id = self.company_id.contribution_cg_id product_com_id = self.company_id.contribution_fede_com_id product_cae_id = self.company_id.contribution_fede_cae_id @@ -422,23 +480,23 @@ class ScopCotisation(models.Model): members = self.get_members() header = [ - 'N° Adhérent', - 'Union Régionale', - 'Forme Coopérative', - 'Organisme', - 'Type de cotisation', - 'Cotisation ' + str(self.year), - 'Cotisation ' + str(self.year - 1), - 'Assiette', - 'Montant Assiette', - 'Année Liasse', - 'Durée Exercice', - 'CA sens CG Scop', - 'VABDF sens CG Scop', - 'Salaires sens CG Scop', - 'Résultat', - 'Dernier effectif connu', - 'Moyen de paiement' + "N° Adhérent", + "Union Régionale", + "Forme Coopérative", + "Organisme", + "Type de cotisation", + "Cotisation " + self.year, + "Cotisation " + str(int(self.year) - 1), + "Assiette", + "Montant Assiette", + "Année Liasse", + "Durée Exercice", + "CA sens CG Scop", + "VABDF sens CG Scop", + "Salaires sens CG Scop", + "Résultat", + "Dernier effectif connu", + "Moyen de paiement", ] # Init variables @@ -448,27 +506,34 @@ class ScopCotisation(models.Model): for m in self.web_progress_iter(members, msg="cotisations calculées"): liasse = self.get_liasse(m) - line_ids = InvoiceLine.search([ - ('partner_id', '=', m.id), - ('invoice_id.state', 'not in', ('draft', 'cancel')), - ('invoice_id.year', '=', self.year - 1) - ]) + line_ids = AccountMoveLine.search( + [ + ("partner_id", "=", m.id), + ("move_id.state", "=", "posted"), + ("move_id.year", "=", int(self.year) - 1), + ("product_id", "!=", False), + ] + ) # Calcul Cotisation CG Scop - net_results = liasse.L2053_HN \ - if liasse.L2053_HN > 0 else liasse.L2051_DI - contrib_cg = self.round_to_closest_multiple( - liasse.contribution_cg, 4) if liasse else 300 + net_results = liasse.L2053_HN if liasse.L2053_HN > 0 else liasse.L2051_DI + contrib_cg = ( + self.round_to_closest_multiple(liasse.contribution_cg, 4) + if liasse + else 300 + ) contribution_amount = contrib_cg contribution_name = type_cotisation_cg.name # Calcul cotisation N-1 - contribution_last_year = sum(line_ids.filtered( - lambda l: l.product_id == product_cg_id).mapped( - 'price_subtotal_signed')) + contribution_last_year = sum( + line_ids.filtered(lambda l: l.product_id == product_cg_id).mapped( + lambda c: c.price_total if c.balance > 0 else -c.price_total + ) + ) # Construction Tableau - liasse.read(['revenue_cg', 'av_cg', 'wage_cg']) + liasse.read(["revenue_cg", "av_cg", "wage_cg"]) datas_contrib = [ m.member_number, m.ur_id.name, @@ -477,7 +542,7 @@ class ScopCotisation(models.Model): contribution_name, contribution_amount, contribution_last_year, - liasse.contribution_base_type.upper() if liasse else 'CA', + liasse.contribution_base_type.upper() if liasse else "CA", liasse.contribution_base_amount, liasse.year, liasse.dureeExercice, @@ -486,42 +551,58 @@ class ScopCotisation(models.Model): liasse.wage_cg, net_results, m.staff_last, - m.customer_payment_mode_id.name if m.customer_payment_mode_id else 'Virement/Chèque', + m.customer_payment_mode_id.name + if m.customer_payment_mode_id + else "Virement/Chèque", ] # Ajout ligne CG Scop datas.append(datas_contrib) - if type_simul == 'all': + if type_simul == "all": # Ajout ligne UR HDF - ur_hdf = self.env.ref('cgscop_partner.riga_14232') + ur_hdf = self.env.ref("cgscop_partner.riga_14232") if m.ur_id == ur_hdf: datas_contrib_hdf = datas_contrib.copy() # Calcul cotisation - contrib_hdf = self.round_to_closest_multiple( - liasse.contribution_hdf, 4) if liasse else 40 + contrib_hdf = ( + self.round_to_closest_multiple(liasse.contribution_hdf, 4) + if liasse + else 40 + ) # Calcul cotisation N-1 - contribution_last_year = sum(line_ids.filtered( - lambda l: l.product_id == product_hdf_id).mapped( - 'price_subtotal_signed')) - datas_contrib_hdf[4] = 'Cotisation UR HDF' + contribution_last_year = sum( + line_ids.filtered( + lambda l: l.product_id == product_hdf_id + ).mapped( + lambda c: c.price_total if c.balance > 0 else -c.price_total + ) + ) + datas_contrib_hdf[4] = "Cotisation UR HDF" datas_contrib_hdf[5] = contrib_hdf datas_contrib_hdf[6] = contribution_last_year datas.append(datas_contrib_hdf) total_hdf += contrib_hdf # Ajout ligne UR Med - ur_med = self.env.ref('cgscop_partner.riga_14243') + ur_med = self.env.ref("cgscop_partner.riga_14243") if m.ur_id == ur_med: datas_contrib_med = datas_contrib.copy() # Calcul cotisation - contrib_med = self.round_to_closest_multiple( - liasse.contribution_med, 4) if liasse else 0 + contrib_med = ( + self.round_to_closest_multiple(liasse.contribution_med, 4) + if liasse + else 0 + ) # Calcul cotisation N-1 - contribution_last_year = sum(line_ids.filtered( - lambda l: l.product_id == product_med_id).mapped( - 'price_subtotal_signed')) - datas_contrib_med[4] = 'Cotisation UR Méditerranée' + contribution_last_year = sum( + line_ids.filtered( + lambda l: l.product_id == product_med_id + ).mapped( + lambda c: c.price_total if c.balance > 0 else -c.price_total + ) + ) + datas_contrib_med[4] = "Cotisation UR Méditerranée" datas_contrib_med[5] = contrib_med datas_contrib_med[6] = contribution_last_year datas.append(datas_contrib_med) @@ -533,7 +614,8 @@ class ScopCotisation(models.Model): # Calcul cotisation if liasse: contrib_fede_com = self.round_to_closest_multiple( - liasse.contribution_com, 4) + liasse.contribution_com, 4 + ) else: staff_id = self.get_last_staff_id(liasse.partner_id) if staff_id.staff_average > 0: @@ -543,10 +625,14 @@ class ScopCotisation(models.Model): if contrib_fede_com < 108: contrib_fede_com = 108 # Calcul cotisation N-1 - contribution_last_year = sum(line_ids.filtered( - lambda l: l.product_id == product_com_id).mapped( - 'price_subtotal_signed')) - datas_contrib_com[4] = 'Cotisation Fédération de la Com' + contribution_last_year = sum( + line_ids.filtered( + lambda l: l.product_id == product_com_id + ).mapped( + lambda c: c.price_total if c.balance > 0 else -c.price_total + ) + ) + datas_contrib_com[4] = "Cotisation Fédération de la Com" datas_contrib_com[5] = contrib_fede_com datas_contrib_com[6] = contribution_last_year datas.append(datas_contrib_com) @@ -557,10 +643,14 @@ class ScopCotisation(models.Model): datas_contrib_cae = datas_contrib.copy() contrib_fede_cae = 100 # Calcul cotisation N-1 - contribution_last_year = sum(line_ids.filtered( - lambda l: l.product_id == product_cae_id).mapped( - 'price_subtotal_signed')) - datas_contrib_cae[4] = 'Cotisation Fédération des CAE' + contribution_last_year = sum( + line_ids.filtered( + lambda l: l.product_id == product_cae_id + ).mapped( + lambda c: c.price_total if c.balance > 0 else -c.price_total + ) + ) + datas_contrib_cae[4] = "Cotisation Fédération des CAE" datas_contrib_cae[5] = contrib_fede_cae datas_contrib_cae[6] = contribution_last_year datas.append(datas_contrib_cae) @@ -570,22 +660,25 @@ class ScopCotisation(models.Model): total_cg += contrib_cg # Génération du ficher Excel - file_name = datetime.strftime(datetime.now(), - '%Y-%m-%d_%Hh%M') + ' Simulation cotisations ' + str( - self.year) + '.xlsx' + file_name = ( + datetime.strftime(datetime.now(), "%Y-%m-%d_%Hh%M") + + " Simulation cotisations " + + self.year + + ".xlsx" + ) output = BytesIO() - workbook = xlsxwriter.Workbook(output, {'in_memory': True}) - worksheet1 = workbook.add_worksheet('Données brutes') + workbook = xlsxwriter.Workbook(output, {"in_memory": True}) + worksheet1 = workbook.add_worksheet("Données brutes") # Intégration Header format_header = workbook.add_format( - {'bg_color': '#eeeeee', 'font_color': '#333333', 'bold': True}) + {"bg_color": "#eeeeee", "font_color": "#333333", "bold": True} + ) for col, h in enumerate(header): worksheet1.write(0, col, h, format_header) # Intégration datas - format_monetary = workbook.add_format( - {'num_format': '#,##0 [$€-407]'}) + format_monetary = workbook.add_format({"num_format": "#,##0 [$€-407]"}) for row, contrib in enumerate(datas): for col, value in enumerate(contrib): @@ -608,44 +701,49 @@ class ScopCotisation(models.Model): mem_bytes = output.read() file_base64 = base64.encodebytes(mem_bytes) - simul_id = self.simul_ids.create({ - 'cotisation_id': self.id, - 'file': file_base64, - 'filename': file_name, - 'type_simul': type_simul, - 'total_member': count_member, - 'total_cg': total_cg, - 'total_hdf': total_hdf, - 'total_com': total_com, - 'total_cae': total_cae, - 'total_med': total_med, - }) + simul_id = self.simul_ids.create( + { + "cotisation_id": self.id, + "file": file_base64, + "filename": file_name, + "type_simul": type_simul, + "total_member": count_member, + "total_cg": total_cg, + "total_hdf": total_hdf, + "total_com": total_com, + "total_cae": total_cae, + "total_med": total_med, + } + ) return { - 'name': 'Simulation cotisation', - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'scop.cotisation.cg.simulation', - 'res_id': simul_id.id, - 'target': 'new', - 'flags': {'mode': 'readonly', 'default_buttons': False} + "name": "Simulation cotisation", + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "scop.cotisation.cg.simulation", + "res_id": simul_id.id, + "target": "new", + "flags": {"mode": "readonly", "default_buttons": False}, } # ------------------------------------------------------ # Global functions # ------------------------------------------------------ - @api.multi def get_liasse(self, member): self.ensure_one() - Liasse = self.env['scop.liasse.fiscale'] - liasse_ids = Liasse.search([ - ('partner_id', '=', member.id), - ('is_qualified', '=', True), - '|', '|', - ('revenue_cgsubv', '>', 0), - ('av_lf', '>', 0), - ('av_cg', '>', 0), - ], order="year desc") + Liasse = self.env["scop.liasse.fiscale"] + liasse_ids = Liasse.search( + [ + ("partner_id", "=", member.id), + ("is_qualified", "=", True), + "|", + "|", + ("revenue_cgsubv", ">", 0), + ("av_lf", ">", 0), + ("av_cg", ">", 0), + ], + order="year desc", + ) if liasse_ids: for liasse in liasse_ids: if liasse.year > 0: @@ -664,7 +762,7 @@ class ScopCotisation(models.Model): :param liasse: :return: """ - liasse.read(['av_lf', 'av_cg']) + liasse.read(["av_lf", "av_cg"]) va = liasse.av_lf if liasse.av_lf > 0 else liasse.av_cg return va @@ -686,12 +784,12 @@ class ScopCotisation(models.Model): """ if ca > 0 and va > 0: if ca <= va * 7 / 3: - type_cotiz = 'ca' + type_cotiz = "ca" else: - type_cotiz = 'va' + type_cotiz = "va" else: if va > 0: - type_cotiz = 'va' + type_cotiz = "va" else: - type_cotiz = 'ca' + type_cotiz = "ca" return type_cotiz diff --git a/models/scop_cotisation_simulation.py b/models/scop_cotisation_simulation.py index 1e46c08ad03e86c78932843222442428a2695704..2e35c4d715ac7e85432fc39064fb12795a0ed33b 100644 --- a/models/scop_cotisation_simulation.py +++ b/models/scop_cotisation_simulation.py @@ -1,11 +1,9 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -import json import logging -import threading -from odoo import models, fields, api, exceptions, registry +from odoo import fields, models _logger = logging.getLogger(__name__) @@ -15,25 +13,29 @@ class ScopCotisation(models.Model): _description = "Simulation cotisations CG" cotisation_id = fields.Many2one( - comodel_name='scop.cotisation.cg', + comodel_name="scop.cotisation.cg", ) - file = fields.Binary('Fichier') + file = fields.Binary("Fichier") filename = fields.Char() type_simul = fields.Selection( - selection=[('all', 'Toutes les cotisation'), ('cgscop', 'Cotisations CG Scop')], - string='Type de simulation' + selection=[ + ("all", "Toutes les cotisation"), + ("cgscop", "Cotisations CG Scop"), + ], + string="Type de simulation", ) - total_member = fields.Integer('Nombre Adhérents') - total_cg = fields.Float('Total CG Scop') - total_hdf = fields.Float('Total UR HDF') - total_med = fields.Float('Total UR Med') - total_com = fields.Float('Total Fédération Com') - total_cae = fields.Float('Total Fédération CAE') + total_member = fields.Integer("Nombre Adhérents") + total_cg = fields.Float("Total CG Scop") + total_hdf = fields.Float("Total UR HDF") + total_med = fields.Float("Total UR Med") + total_com = fields.Float("Total Fédération Com") + total_cae = fields.Float("Total Fédération CAE") def get_simul_file(self): return { - 'type': 'ir.actions.act_url', - 'name': 'simulation', - 'url': '/web/content/scop.cotisation.cg.simulation/%s/file/%s?download=true' % (self.id, self.filename), + "type": "ir.actions.act_url", + "name": "simulation", + "url": "/web/content/scop.cotisation.cg.simulation/%s/file/%s?download=true" + % (self.id, self.filename), } diff --git a/models/scop_liasse_fiscale.py b/models/scop_liasse_fiscale.py index a736ec9313ce5bf7c1f9877779810d14e39b34cf..70afb7c0141e26ac5f3057153e12648069abf484 100644 --- a/models/scop_liasse_fiscale.py +++ b/models/scop_liasse_fiscale.py @@ -1,62 +1,70 @@ # © 2021 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, api +from odoo import api, fields, models class ScopLiasseFiscale(models.Model): _inherit = "scop.liasse.fiscale" contribution_cg = fields.Float( - string='Cotisation CG Scop', - compute='_compute_contribution_cg', - store=True) + string="Cotisation CG Scop", + compute="_compute_contribution_cg", + store=True, + ) contribution_base_type = fields.Selection( - string='Type Assiette de cotisation', - selection=[('ca', 'CA'), - ('va', 'VA'), ], - compute='_compute_contribution_cg', - store=True) + string="Type Assiette de cotisation", + selection=[ + ("ca", "CA"), + ("va", "VA"), + ], + compute="_compute_contribution_cg", + store=True, + ) contribution_base_amount = fields.Integer( - string='Montant Assiette de cotisation', - compute='_compute_contribution_cg', - store=True) + string="Montant Assiette de cotisation", + compute="_compute_contribution_cg", + store=True, + ) contribution_hdf = fields.Float( - string='Cotisation UR HDF', - compute='_compute_contribution_hdf', - store=True) + string="Cotisation UR HDF", + compute="_compute_contribution_hdf", + store=True, + ) contribution_med = fields.Float( - string='Cotisation UR Méditerranée', - compute='_compute_contribution_med', - store=True) + string="Cotisation UR Méditerranée", + compute="_compute_contribution_med", + store=True, + ) contribution_com = fields.Float( - string='Cotisation Fédération Com', - compute='_compute_contribution_com', - store=True) + string="Cotisation Fédération Com", + compute="_compute_contribution_com", + store=True, + ) contribution_cae = fields.Float( - string='Cotisation Fédération CAE', - compute='_compute_contribution_cae', - store=True) + string="Cotisation Fédération CAE", + compute="_compute_contribution_cae", + store=True, + ) # ------------------------------------------------------ # Compute fields # ------------------------------------------------------ - @api.depends('av_lf', 'av_cg', 'revenue_cg', 'dureeExercice') - @api.multi + @api.depends("av_lf", "av_cg", "revenue_cg", "dureeExercice") def _compute_contribution_cg(self): """ - Calcule la cotisation de la CG Scop : - - VA = VA saisie ou VA au sens CGSCOP si pas de VA renseignée - - 0,3% du CA ou 0,7% de la VA - - 300 € pour CA compris entre 0 et 100 K€ - - 600 € pour CA compris entre 100 et 200 K€ - - Max = 375 K€ - - @return float : cotisation + Calcule la cotisation de la CG Scop : + - VA = VA saisie ou VA au sens CGSCOP si pas de VA renseignée + - 0,3% du CA ou 0,7% de la VA + - 300 € pour CA compris entre 0 et 100 K€ + - 600 € pour CA compris entre 100 et 200 K€ + - Max = 375 K€ + + @return float : cotisation """ for liasse in self: # Calcul VA - liasse.read(['av_lf', 'av_cg', 'revenue_cg']) + liasse.read(["av_lf", "av_cg", "revenue_cg"]) va = liasse.av_lf if liasse.av_lf > 0 else liasse.av_cg ca = liasse.revenue_cg if liasse.dureeExercice and liasse.dureeExercice not in (0, 12): @@ -66,17 +74,17 @@ class ScopLiasseFiscale(models.Model): # Calcul Type Assiette if ca > 0 and va > 0: if ca <= va * 7 / 3: - contribution_base_type = 'ca' + contribution_base_type = "ca" contribution_base_amount = ca else: - contribution_base_type = 'va' + contribution_base_type = "va" contribution_base_amount = va else: if va > 0: - contribution_base_type = 'va' + contribution_base_type = "va" contribution_base_amount = va else: - contribution_base_type = 'ca' + contribution_base_type = "ca" contribution_base_amount = ca liasse.contribution_base_type = contribution_base_type @@ -86,47 +94,49 @@ class ScopLiasseFiscale(models.Model): values = self.get_values_for_cotiz_cg(liasse.partner_id) # Calcul Cotisation CG Scop - if contribution_base_type == 'ca': + if contribution_base_type == "ca": rate = self.get_rate_ca(liasse.partner_id) contribution = ca * rate else: rate = self.get_rate_va(liasse.partner_id) contribution = va * rate - if contribution < values['plancher1']: - liasse.contribution_cg = values['plancher1'] - elif contribution < values['plancher2']: - liasse.contribution_cg = values['plancher2'] - elif contribution >= values['plancher3']: - if contribution_base_type == 'ca': + if contribution < values["plancher1"]: + liasse.contribution_cg = values["plancher1"] + elif contribution < values["plancher2"]: + liasse.contribution_cg = values["plancher2"] + elif contribution >= values["plancher3"]: + if contribution_base_type == "ca": contribution = (25000000 * rate) + (ca - 25000000) * (rate / 2) else: contribution = (10714286 * rate) + (va - 10714286) * (rate / 2) - if contribution <= values['plafond']: + if contribution <= values["plafond"]: liasse.contribution_cg = contribution else: - liasse.contribution_cg = values['plafond'] + liasse.contribution_cg = values["plafond"] else: liasse.contribution_cg = contribution - @api.depends('wage_cg') - @api.multi + @api.depends("wage_cg") def _compute_contribution_hdf(self): """ - Calcule la cotisation de l'UR HDF pour 1 partenaire : - - 0,1 % de la masse salariale annuelle brute prévisionnelle - ou figurant sur la liasse fiscale. + Calcule la cotisation de l'UR HDF pour 1 partenaire : + - 0,1 % de la masse salariale annuelle brute prévisionnelle + ou figurant sur la liasse fiscale. - @return float : cotisation + @return float : cotisation """ - ur_hdf = self.env.ref('cgscop_partner.riga_14232') + ur_hdf = self.env.ref("cgscop_partner.riga_14232") for liasse in self: - plancher = liasse.get_plancher_cotiz()['ur_hdf'] - liasse.read(['wage_cg']) + plancher = liasse.get_plancher_cotiz()["ur_hdf"] + liasse.read(["wage_cg"]) if liasse.partner_id.ur_id == ur_hdf: rate = 0.001 - if liasse.dureeExercice and liasse.dureeExercice not in (0, 12): - wage_cg = liasse.wage_cg * (12/liasse.dureeExercice) + if liasse.dureeExercice and liasse.dureeExercice not in ( + 0, + 12, + ): + wage_cg = liasse.wage_cg * (12 / liasse.dureeExercice) else: wage_cg = liasse.wage_cg if wage_cg > 0: @@ -139,39 +149,43 @@ class ScopLiasseFiscale(models.Model): else: liasse.contribution_hdf = plancher - @api.depends('contribution_cg', 'L2053_HN') - @api.multi + @api.depends("contribution_cg", "L2053_HN") def _compute_contribution_med(self): """ - Calcule la cotisation de l'UR Med pour 1 liasse : - - Assiette : Assiette de la cotisation CGSCOP - - Taux d’appel : 1/3 du taux - - Calcul intermédiaire : Assiette * taux - (soit 1/3 de la cotisation CGSCOP sans plancher) - - Complément de cotisation : 1% du résultat net si positif - - Abattement pour sociétariat : - Taux de sociétariat = nombre de salariés sociétaires / - nombre de salariés - Abattement 20 % si >= 50 % - Abattement 30 % si >= 80 % - - Calcul cotisations : - [(Assiette*taux) + (résultat net *0.01)]* (1 ou 0.8 ou 0.7) - - @return float : cotisation + Calcule la cotisation de l'UR Med pour 1 liasse : + - Assiette : Assiette de la cotisation CGSCOP + - Taux d’appel : 1/3 du taux + - Calcul intermédiaire : Assiette * taux + (soit 1/3 de la cotisation CGSCOP sans plancher) + - Complément de cotisation : 1% du résultat net si positif + - Abattement pour sociétariat : + Taux de sociétariat = nombre de salariés sociétaires / + nombre de salariés + Abattement 20 % si >= 50 % + Abattement 30 % si >= 80 % + - Calcul cotisations : + [(Assiette*taux) + (résultat net *0.01)]* (1 ou 0.8 ou 0.7) + + @return float : cotisation """ - ur_med = self.env.ref('cgscop_partner.riga_14243') + ur_med = self.env.ref("cgscop_partner.riga_14243") for liasse in self: - plancher = liasse.get_plancher_cotiz()['ur_med'] + plancher = liasse.get_plancher_cotiz()["ur_med"] if liasse.partner_id.ur_id == ur_med: # Assiette CG - assiette_rate = 1/3 + assiette_rate = 1 / 3 assiette = liasse.contribution_cg # Résultat net net_results_rate = 0.01 - net_results = liasse.L2053_HN if liasse.L2053_HN > 0 else liasse.L2051_DI - if liasse.dureeExercice and liasse.dureeExercice not in (0, 12): - net_results = net_results * (12/liasse.dureeExercice) + net_results = ( + liasse.L2053_HN if liasse.L2053_HN > 0 else liasse.L2051_DI + ) + if liasse.dureeExercice and liasse.dureeExercice not in ( + 0, + 12, + ): + net_results = net_results * (12 / liasse.dureeExercice) # Effectifs staff_id = self.get_last_staff_id(liasse.partner_id) @@ -195,38 +209,43 @@ class ScopLiasseFiscale(models.Model): abatt_rate = 1 - 0 # Calcul Cotisation - contribution_med = ((assiette * assiette_rate) + - (net_results * net_results_rate)) * abatt_rate - final_contribution_med = contribution_med if contribution_med >= 0 else plancher + contribution_med = ( + (assiette * assiette_rate) + (net_results * net_results_rate) + ) * abatt_rate + final_contribution_med = ( + contribution_med if contribution_med >= 0 else plancher + ) liasse.contribution_med = final_contribution_med - @api.depends('av_lf', 'av_cg') - @api.multi + @api.depends("av_lf", "av_cg") def _compute_contribution_com(self): """ - Calcule la cotisation de la fédération de la com pour 1 partenaire - - Assiette annuelle : VA saisie ou VA au sens CGSCOP - - Taux : 0.0032 - - Calcul : Valeur Ajoutée * 0.0032 - - Pour les nouvelles coopératives (pas de comptes annuels) : - 108 € par salarié (effectif moyen s’il est saisi, à défaut - effectif), soit 27 € par salarié et par trimestre. - - Plancher annuel : 108 € - - Plafond annuel : 18 428 € - - @return float : cotisation + Calcule la cotisation de la fédération de la com pour 1 partenaire + - Assiette annuelle : VA saisie ou VA au sens CGSCOP + - Taux : 0.0032 + - Calcul : Valeur Ajoutée * 0.0032 + - Pour les nouvelles coopératives (pas de comptes annuels) : + 108 € par salarié (effectif moyen s’il est saisi, à défaut + effectif), soit 27 € par salarié et par trimestre. + - Plancher annuel : 108 € + - Plafond annuel : 18 428 € + + @return float : cotisation """ plafond = 18428 rate = 0.0032 for liasse in self: - plancher = liasse.get_plancher_cotiz()['fede_com'] - liasse.read(['av_lf', 'av_cg']) + plancher = liasse.get_plancher_cotiz()["fede_com"] + liasse.read(["av_lf", "av_cg"]) if liasse.partner_id.is_federation_com: # Calcul VA va = liasse.av_lf if liasse.av_lf > 0 else liasse.av_cg # Calcul VA proratisée - if liasse.dureeExercice and liasse.dureeExercice not in (0, 12): + if liasse.dureeExercice and liasse.dureeExercice not in ( + 0, + 12, + ): va = va * (12 / liasse.dureeExercice) else: va = va @@ -255,19 +274,18 @@ class ScopLiasseFiscale(models.Model): else: liasse.contribution_com = plafond - @api.depends('L2052_FY', 'partner_id.cae') - @api.multi + @api.depends("L2052_FY", "partner_id.cae") def _compute_contribution_cae(self): """ - Calcule la cotisation CAE 1 partenaire : - - 0,4 % de la masse salariale annuelle brute - - plancher = 300 - - plafond = 8500 - @return float : cotisation + Calcule la cotisation CAE 1 partenaire : + - 0,4 % de la masse salariale annuelle brute + - plancher = 300 + - plafond = 8500 + @return float : cotisation """ for liasse in self: if liasse.partner_id.cae: - plancher = liasse.get_plancher_cotiz()['fede_cae'] + plancher = liasse.get_plancher_cotiz()["fede_cae"] plafond = 8500 rate = 0.004 contribution_cae = 0 @@ -302,15 +320,14 @@ class ScopLiasseFiscale(models.Model): abatt_rate_med = 1 - 0.3 else: abatt_rate_med = 1 - 0 - assiette_rate_med = 1/3 - plancher_cg = self.get_values_for_cotiz_cg( - self.partner_id)['plancher1'] + assiette_rate_med = 1 / 3 + plancher_cg = self.get_values_for_cotiz_cg(self.partner_id)["plancher1"] return { - 'fede_com': 108, - 'fede_cae': 300, - 'ur_med': plancher_cg * assiette_rate_med * abatt_rate_med, - 'ur_hdf': 40, + "fede_com": 108, + "fede_cae": 300, + "ur_med": plancher_cg * assiette_rate_med * abatt_rate_med, + "ur_hdf": 40, } def get_values_for_cotiz_cg(self, partner): @@ -320,25 +337,27 @@ class ScopLiasseFiscale(models.Model): plancher3 = 75000 plafond = 375000 if partner.cooperative_form_id in ( - self.env.ref('cgscop_partner.form_coop47'), - self.env.ref('cgscop_partner.form_lamaneur')): + self.env.ref("cgscop_partner.form_coop47"), + self.env.ref("cgscop_partner.form_lamaneur"), + ): plancher1 = 1 / 3 * plancher1 plancher2 = 1 / 3 * plancher2 plancher3 = 1 / 3 * plancher3 plafond = 1 / 3 * plafond return { - 'plancher1': plancher1, - 'plancher2': plancher2, - 'plancher3': plancher3, - 'plafond': plafond, + "plancher1": plancher1, + "plancher2": plancher2, + "plancher3": plancher3, + "plafond": plafond, } def get_rate_ca(self, partner): # Calcul des Taux SCOP en fonction du type if partner.cooperative_form_id in ( - self.env.ref('cgscop_partner.form_coop47'), - self.env.ref('cgscop_partner.form_lamaneur')): + self.env.ref("cgscop_partner.form_coop47"), + self.env.ref("cgscop_partner.form_lamaneur"), + ): rate_ca = 0.002 else: rate_ca = 0.003 @@ -347,8 +366,9 @@ class ScopLiasseFiscale(models.Model): def get_rate_va(self, partner): # Calcul des Taux SCOP en fonction du type if partner.cooperative_form_id in ( - self.env.ref('cgscop_partner.form_coop47'), - self.env.ref('cgscop_partner.form_lamaneur')): + self.env.ref("cgscop_partner.form_coop47"), + self.env.ref("cgscop_partner.form_lamaneur"), + ): rate_va = 0.0047 else: rate_va = 0.007 diff --git a/report/__init__.py b/report/__init__.py old mode 100755 new mode 100644 diff --git a/report/scop_contribution_report.py b/report/scop_contribution_report.py index f5b1841402e24a6f7c230083a9ccafa2fdf69121..27fa8e87224eeada892e600975875b9c8228fa65 100644 --- a/report/scop_contribution_report.py +++ b/report/scop_contribution_report.py @@ -1,7 +1,7 @@ # © 2022 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, api +from odoo import _, fields, models from odoo.exceptions import UserError @@ -13,17 +13,22 @@ class ScopContributionReport(models.Model): # ------------------------------------------------------ # Compute # ------------------------------------------------------ - @api.multi def _compute_has_bordereau(self): - contrib_cg = self.env.ref('cgscop_partner.riga_14397') + contrib_cg = self.env.ref("cgscop_partner.riga_14397") for contribution in self: # exclude contribution before 2021 from RIGA - if contribution.year > '2020': + if contribution.year > "2020": if contribution.type_contribution_id == contrib_cg: - bordereau = self.env['scop.bordereau'].sudo().search([ - ('partner_id', '=', self.partner_id.id), - ('year', '=', self.year), - ]) + bordereau = ( + self.env["scop.bordereau"] + .sudo() + .search( + [ + ("partner_id", "=", self.partner_id.id), + ("year", "=", self.year), + ] + ) + ) if len(bordereau) == 1: contribution.has_bordereau = True else: @@ -37,16 +42,26 @@ class ScopContributionReport(models.Model): # Button # ------------------------------------------------------ def print_report_with_payment(self): - bordereau = self.env['scop.bordereau'].sudo().search([ - ('partner_id', '=', self.partner_id.id), - ('year', '=', self.year), - ]) + bordereau = ( + self.env["scop.bordereau"] + .sudo() + .search( + [ + ("partner_id", "=", self.partner_id.id), + ("year", "=", self.year), + ] + ) + ) if len(bordereau) == 1: - return self.env.ref( - 'cgscop_cotisation_cg.cgscop_bordereau_report_with_payments' - ).sudo().report_action(bordereau.sudo()) + return ( + self.env.ref( + "cgscop_cotisation_cg.cgscop_bordereau_report_with_payments" + ) + .sudo() + .report_action(bordereau.sudo()) + ) else: - raise UserError('Pas de bordereau rattaché à cette cotisation.') + raise UserError(_("Pas de bordereau rattaché à cette cotisation.")) # ------------------------------------------------------ # Business method @@ -56,11 +71,27 @@ class ScopContributionReport(models.Model): If cotiz is type CG, then we filtered on not canceled bordereaux """ self.ensure_one() - invoice_ids = super( - ScopContributionReport, self).get_invoice_contribution() - contribution_cg = self.env.ref('cgscop_partner.riga_14397') + invoice_ids = super(ScopContributionReport, self).get_invoice_contribution() + contribution_cg = self.env.ref("cgscop_partner.riga_14397") if self.type_contribution_id == contribution_cg: invoice_ids = invoice_ids.filtered( - lambda i: i.bordereau_id.state not in ('cancel',) + lambda i: i.bordereau_id.state not in ("cancel",) ) return invoice_ids + + # ------------------------------------------------------ + # Inherit parent + # ------------------------------------------------------ + def _get_contribution_domain(self): + """ + Hérite la fonction parente pour ajouter la notion de bordereau + dans la vue pour les cotisations CG + """ "" + domain = super()._get_contribution_domain() + domain.append( + "|", + ("bordereau_id.state", "not in", ("cancel", "new")), + ("bordereau_id", "=", False), + ) + print(domain) + return domain diff --git a/report/scop_contribution_report.xml b/report/scop_contribution_report.xml index bdf5c4451458a18b10a3b0ab5e1582fcb31cf336..b305fe78b1dfe3b8b41e1cd88506dd17fd2479e0 100644 --- a/report/scop_contribution_report.xml +++ b/report/scop_contribution_report.xml @@ -1,20 +1,27 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data> <!-- FORM VIEW --> <record model="ir.ui.view" id="scop_contribution_report_cg_form"> <field name="name">scop.contribution.report.cg.form</field> <field name="model">scop.contribution.report</field> - <field name="inherit_id" ref="cgscop_cotisation.scop_contribution_report_form"/> + <field + name="inherit_id" + ref="cgscop_cotisation.scop_contribution_report_form" + /> <field name="arch" type="xml"> <xpath expr="//field[@name='payments']" position="before"> - <field name="has_bordereau" invisible="1"/> - <div attrs="{'invisible': [('has_bordereau', '=', False)]}" class="mt16 mb16"> - <button name="print_report_with_payment" - type="object" - string="Imprimer le bordereau" - icon="fa-file-pdf-o" - class="btn btn-sm btn-outline-info" + <field name="has_bordereau" invisible="1" /> + <div + attrs="{'invisible': [('has_bordereau', '=', False)]}" + class="mt16 mb16" + > + <button + name="print_report_with_payment" + type="object" + string="Imprimer le bordereau" + icon="fa-file-pdf-o" + class="btn btn-sm btn-outline-info" /> </div> </xpath> diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv old mode 100755 new mode 100644 index 658ea35458a8044306a690cf97ee97080993a6c5..7c925ce5c5125d83851fe69bb5190e6790cc78cb --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -9,3 +9,11 @@ access_scop_bordereau_version,access_scop_bordereau_version,model_scop_bordereau admin_access_scop_bordereau_version,admin_access_scop_bordereau_version,model_scop_bordereau_version,cgscop_partner.group_cg_administrator,1,1,1,1 access_scop_bordereau_refund_wizard_quarter,access_scop_bordereau_refund_wizard_quarter,model_scop_bordereau_refund_wizard_quarter,cgscop_cotisation_cg.group_cotisation_cg_administrative,1,1,1,1 admin_access_scop_bordereau_refund_wizard_quarter,admin_access_scop_bordereau_refund_wizard_quarter,model_scop_bordereau_refund_wizard_quarter,cgscop_partner.group_cg_administrator,1,1,1,1 +access_scop_bordereau_refund_wizard,access_scop_bordereau_refund_wizard,model_scop_bordereau_refund_wizard,base.group_user,1,1,1,1 +access_scop_bordereau_update,access_scop_bordereau_update,model_scop_bordereau_update,base.group_user,1,1,1,1 +access_scop_bordereau_validate,access_scop_bordereau_validate,model_scop_bordereau_validate,base.group_user,1,1,1,1 +access_scop_cotisation_regul_wizard,access_scop_cotisation_regul_wizard,model_scop_cotisation_regul_wizard,base.group_user,1,1,1,1 +access_scop_cotisation_cg_wizard,access_scop_cotisation_cg_wizard,model_scop_cotisation_cg_wizard,base.group_user,1,1,1,1 +access_export_journal_cg_wizard,access_export_journal_cg_wizard,model_export_journal_cg_wizard,base.group_user,1,1,1,1 +access_scop_bordereau_change_liasse_wizard,access_scop_bordereau_change_liasse_wizard,model_scop_bordereau_change_liasse_wizard,base.group_user,1,1,1,1 +access_scop_bordereau_change_payment_mode_wizard,access_scop_bordereau_change_payment_mode_wizard,model_scop_bordereau_change_payment_mode_wizard,base.group_user,1,1,1,1 diff --git a/security/security_rules.xml b/security/security_rules.xml index a4f7a2f581cf2101a68e0cbb1fd3ebf96e4a448e..1fe8d71ee35b849d557e1877bd618bec983cc83a 100644 --- a/security/security_rules.xml +++ b/security/security_rules.xml @@ -1,22 +1,25 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <!-- Copyright 2020 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> - <data noupdate="0"> + <data> <!-- Categories & Groups --> <!-- Add Cotisations group category --> <record model="ir.module.category" id="cgscop_cotisation_cg_module_category"> <field name="name">Cotisation</field> + <field name="parent_id" ref="cgscop_partner.module_cgscop_category" /> </record> <!-- Add cotisations groups --> <record id="group_cotisation_cg_administrative" model="res.groups"> <field name="name">Gestionnaire des cotisations</field> - <field name="category_id" ref="cgscop_cotisation_cg_module_category"/> - <field name="implied_ids" eval="[(6, 0, [ref('account.group_account_manager')])]"/> + <field name="category_id" ref="cgscop_cotisation_cg_module_category" /> + <field + name="implied_ids" + eval="[(6, 0, [ref('account.group_account_manager')])]" + /> </record> <!-- Rules --> @@ -24,46 +27,66 @@ <!-- Cotiz only for own company --> <record id="cg_cotisation_cg_rule" model="ir.rule"> <field name="name">Cotisations consultables que pour sa société</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_cotisation_cg"/> - <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> + <field + name="model_id" + ref="cgscop_cotisation_cg.model_scop_cotisation_cg" + /> + <field + name="domain_force" + >['|',('company_id','=',False),('company_id','in',company_ids)]</field> + <field name="perm_read" eval="True" /> + <field name="perm_write" eval="True" /> + <field name="perm_create" eval="True" /> + <field name="perm_unlink" eval="True" /> </record> <!-- Bordereaux only for own company --> - <record id="cg_cotisation_cg_rule" model="ir.rule"> + <record id="scop_bordereau_rule" model="ir.rule"> <field name="name">Bordereaux consultables que pour sa société</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau"/> - <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> + <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau" /> + <field + name="domain_force" + >['|',('company_id','=',False),('company_id','in',company_ids)]</field> + <field name="perm_read" eval="True" /> + <field name="perm_write" eval="True" /> + <field name="perm_create" eval="True" /> + <field name="perm_unlink" eval="True" /> </record> <!-- Service Admin grant all access --> <record id="scop_cotisation_cg_admin" model="ir.rule"> - <field name="name">Cotisations - Modification - Service Administratif</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_cotisation_cg"/> + <field + name="name" + >Cotisations - Modification - Service Administratif</field> + <field + name="model_id" + ref="cgscop_cotisation_cg.model_scop_cotisation_cg" + /> <field name="domain_force">[(1,'=',1)]</field> - <field name="groups" eval="[(6, 0, [ref('group_cotisation_cg_administrative')])]"/> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> + <field + name="groups" + eval="[(6, 0, [ref('group_cotisation_cg_administrative')])]" + /> + <field name="perm_read" eval="True" /> + <field name="perm_write" eval="True" /> + <field name="perm_create" eval="True" /> + <field name="perm_unlink" eval="True" /> </record> <record id="scop_bordereau_admin" model="ir.rule"> - <field name="name">Bordereaux - Modification - Service Administratif</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau"/> + <field + name="name" + >Bordereaux - Modification - Service Administratif</field> + <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau" /> <field name="domain_force">[(1,'=',1)]</field> - <field name="groups" eval="[(6, 0, [ref('group_cotisation_cg_administrative')])]"/> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> + <field + name="groups" + eval="[(6, 0, [ref('group_cotisation_cg_administrative')])]" + /> + <field name="perm_read" eval="True" /> + <field name="perm_write" eval="True" /> + <field name="perm_create" eval="True" /> + <field name="perm_unlink" eval="True" /> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/static/description/icon.png b/static/description/icon.png old mode 100755 new mode 100644 index 82ef47760a441cf229b5009f0a18ccf3842fbfa5..499652a2c9c0307f875bafc145b6fbafa133da72 Binary files a/static/description/icon.png and b/static/description/icon.png differ diff --git a/templates/report_scop_bordereau.xml b/templates/report_scop_bordereau.xml index 2457b564f0b6b858118cb91f5c5c1898611bb337..e6db969b547751e76615e3c339273adb8fa70763 100644 --- a/templates/report_scop_bordereau.xml +++ b/templates/report_scop_bordereau.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data> @@ -9,116 +9,209 @@ <div class="row"> <div class="col-6 offset-6 mt64 mb64"> - <span t-field="o.partner_id.name" style="text-transform: uppercase; font-weight: 600;"/><br/> - <span t-field="o.partner_id.street" /><br/> - <t t-if="o.partner_id.street2"><span t-field="o.partner_id.street2"/><br/></t> - <t t-if="o.partner_id.street3"><span t-field="o.partner_id.street3"/><br/></t> - <span t-field="o.partner_id.zip" /> <span t-field="o.partner_id.city" style="text-transform: uppercase;"/> - <t t-if="o.partner_id.cedex"> <span t-field="o.partner_id.cedex"/></t> + <span + t-field="o.partner_id.name" + style="text-transform: uppercase; font-weight: 600;" + /><br /> + <span t-field="o.partner_id.street" /><br /> + <t t-if="o.partner_id.street2"><span + t-field="o.partner_id.street2" + /><br /></t> + <t t-if="o.partner_id.street3"><span + t-field="o.partner_id.street3" + /><br /></t> + <span t-field="o.partner_id.zip" /> <span + t-field="o.partner_id.city" + style="text-transform: uppercase;" + /> + <t t-if="o.partner_id.cedex"> <span + t-field="o.partner_id.cedex" + /></t> </div> </div> <div class="row"> <div class="col-12 text-center"> <h2 style="color: #E5074D;"> - Appel de cotisation <span t-esc="str(o.year)"/> + Appel de cotisation <span t-esc="str(o.year)" /> </h2> </div> </div> <div class="row"> <div class="col-12 mb16"> <p> - Paris, le <span t-esc="o.date_cotisation" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> + Paris, le <span + t-esc="o.date_cotisation" + t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}" + /> </p> <p> - N° adhérent : <t t-esc="str(o.partner_id.member_number_int)"/><br/> - Union régionale : <span t-field="o.partner_ur_id.name"/><br/> - N° Bordereau : <span t-field="o.name"/><t t-if="o.is_regul">-<span t-field="o.version"/></t> + N° adhérent : <t + t-esc="str(o.partner_id.member_number_int)" + /><br /> + Union régionale : <span + t-field="o.partner_ur_id.name" + /><br /> + N° Bordereau : <span t-field="o.name" /><t + t-if="o.is_regul" + >-<span t-field="o.version" /></t> </p> </div> </div> <div class="row mb16"> - <div class="col-12" style="font-style: italic; test-align: justify;"> + <div + class="col-12" + style="font-style: italic; test-align: justify;" + > Les cotisations sont calculées annuellement en début d’année sur la base du dernier exercice connu. Le versement se fait par quart tous les trimestres. Merci de retourner ce bordereau à la CG Scop avec le règlement correspondant </div> </div> <div class="row"> <div class="col-6" style="border: 1px solid #aaa;"> - <div></div> - <h5 class="mt8" style="font-weight: 600;">Cotisations annuelles</h5> + <div /> + <h5 + class="mt8" + style="font-weight: 600;" + >Cotisations annuelles</h5> <p style="font-style: italic; font-size: 13px;"> - <t t-if="o.year_liasse">Calcul basé sur la liasse fiscale + <t + t-if="o.year_liasse" + >Calcul basé sur la liasse fiscale <t t-if="o.is_liasse_previ"> - <span>Prévisionnelle</span><br/> + <span>Prévisionnelle</span><br /> </t> <t t-else=""> - <span t-esc="str(o.year_liasse)" /><br/> + <span t-esc="str(o.year_liasse)" /><br /> </t> </t> - Assiette base <span t-field="o.type_assiette" /> : <span t-field="o.montant_assiette" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" />. + Assiette base <span t-field="o.type_assiette" /> : <span + t-field="o.montant_assiette" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + />. </p> <p> - <t t-set="amount_line" t-value="o.get_contribution_type()" /> + <t + t-set="amount_line" + t-value="o.get_contribution_type()" + /> <table class="table table-sm" style="border: none;"> - <tr t-foreach="amount_line" t-as="line" style="border-bottom: 1px solid #ccc;"> - <td style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('type_contribution_id')[1]"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('amount_total_signed')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <tr + t-foreach="amount_line" + t-as="line" + style="border-bottom: 1px solid #ccc;" + > + <td + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('type_contribution_id')[1]" + /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('amount_total_signed')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </tr> </table> </p> <p> <table class="table table-sm" style="border: none;"> <tr style="border: none"> - <td style="border: none; background: inherit; color: inherit;"> - <strong>Total cotisation annuelle <t t-esc="str(o.year)"/>*</strong> + <td + style="border: none; background: inherit; color: inherit;" + > + <strong>Total cotisation annuelle <t + t-esc="str(o.year)" + />*</strong> </td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + > <t t-if="o.is_regul"> - <strong><span t-esc="sum(o.invoice_ids.filtered(lambda i: i.type == 'out_invoice').mapped('amount_total_signed'))" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></strong> + <strong><span + t-esc="sum(o.invoice_ids.filtered(lambda i: i.move_type == 'out_invoice').mapped('amount_total_signed'))" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></strong> </t> <t t-else=""> - <strong><span t-field="o.amount_total_cotiz" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></strong> + <strong><span + t-field="o.amount_total_cotiz" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></strong> </t> </td> </tr> </table> </p> <t t-if="o.is_sdd"> - <h5 style="font-weight: 600;">Échéancier de prélèvement</h5> + <h5 + style="font-weight: 600;" + >Échéancier de prélèvement</h5> </t> <t t-else=""> - <h5 style="font-weight: 600;">Échéancier de paiement</h5> + <h5 + style="font-weight: 600;" + >Échéancier de paiement</h5> </t> <p id="schedule_table"> - <t t-set="schedule_line" t-value="o.get_bordereau_move_line()" /> - <table class="table table-sm table-striped" style="border: none;"> - <tr t-foreach="schedule_line" t-as="line" style="border-bottom: 1px solid #ccc;"> - <td style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('date')"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('amount')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <t + t-set="schedule_line" + t-value="o.get_bordereau_move_line()" + /> + <table + class="table table-sm table-striped" + style="border: none;" + > + <tr + t-foreach="schedule_line" + t-as="line" + style="border-bottom: 1px solid #ccc;" + > + <td + style="border: none; background: inherit; color: inherit;" + ><t t-esc="line.get('date')" /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('amount')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </tr> </table> </p> - <p t-if="o.is_sdd" style="font-size: 13px; font-weight: bold;"> + <p + t-if="o.is_sdd" + style="font-size: 13px; font-weight: bold;" + > Référence Unique du Mandat : - <t t-esc="o.invoice_ids[0].mandate_id.unique_mandate_reference" /> + <t + t-esc="o.invoice_ids[0].mandate_id.unique_mandate_reference" + /> </p> <t t-if="not o.is_sdd"> <p class="small"> - Si vous souhaitez régler vos prochaines cotisations par prélèvement,merci de compléter et de nous retourner le document « Mandat de prélèvements SEPA » (disponible sur notre site) à l'adresse <a href="mailto:les-scop@scop.coop">les-scop@scop.coop</a>, accompagné d’un Relevé d’identité bancaire + Si vous souhaitez régler vos prochaines cotisations par prélèvement,merci de compléter et de nous retourner le document « Mandat de prélèvements SEPA » (disponible sur notre site) à l'adresse <a + href="mailto:les-scop@scop.coop" + >les-scop@scop.coop</a>, accompagné d’un Relevé d’identité bancaire </p> </t> <p class="small"> - <em>* Inclus abonnement annuel à la Revue Participer au tarif préférentiel adhérent de 22 € TTC</em> + <em + >* Inclus abonnement annuel à la Revue Participer au tarif préférentiel adhérent de 22 € TTC</em> </p> <p style="font-size: 13px;"> - <em>IBAN: FR76 4255 9100 0008 0024 8837 710 - BIC : CCOPFRPPXXX</em> + <em + >IBAN: FR76 4255 9100 0008 0024 8837 710 - BIC : CCOPFRPPXXX</em> </p> </div> <div class="col-6" style="margin-top: 220px;"> <div style="border: 1px solid #aaa; padding: 15px;"> - CG Scop <br/> - 30, rue des Epinettes <br/> + CG Scop <br /> + 30, rue des Epinettes <br /> 75017 PARIS </div> </div> @@ -128,33 +221,46 @@ <div class="row"> <div class="col-12"> <p> - <strong>COTISATION A LA CONFÉDÉRATION GÉNÉRALE DES SCOP</strong> + <strong + >COTISATION A LA CONFÉDÉRATION GÉNÉRALE DES SCOP</strong> </p> <p> - La cotisation est calculée selon la méthode la plus favorable entre trois pour mille du chiffre d’affaires et sept pour mille de la valeur ajoutée.<br/> - La valeur ajoutée retenue est celle de la liasse fiscale ou, si elle n’est pas connue, la valeur ajoutée telle que définie par la Banque de France :<br/> - <i>Valeur ajoutée = total des chiffres d’affaires nets(FL) et subventions d’exploitation(FO) + production stockée(FM) + production immobilisée(FN) - achat de marchandises(FS) - variation de stock marchandises(FT) - achat de matières premières et autres approvisionnements(FU) - variation de stock matières premières et approvisionnements(FV) - autres achats et charges externes(FW)(déduction faite du personnel extérieur et des loyers de crédit - bail) - impôts et taxes(FX).</i> + La cotisation est calculée selon la méthode la plus favorable entre trois pour mille du chiffre d’affaires et sept pour mille de la valeur ajoutée.<br + /> + La valeur ajoutée retenue est celle de la liasse fiscale ou, si elle n’est pas connue, la valeur ajoutée telle que définie par la Banque de France :<br + /> + <i + >Valeur ajoutée = total des chiffres d’affaires nets(FL) et subventions d’exploitation(FO) + production stockée(FM) + production immobilisée(FN) - achat de marchandises(FS) - variation de stock marchandises(FT) - achat de matières premières et autres approvisionnements(FU) - variation de stock matières premières et approvisionnements(FV) - autres achats et charges externes(FW)(déduction faite du personnel extérieur et des loyers de crédit - bail) - impôts et taxes(FX).</i> </p> <p> - Le calcul de la cotisation est établi une fois par an en début d’année à partir des comptes de résultat du dernier exercice connu, ou du prévisionnel pour les nouveaux adhérents qui n’ont pas encore de compte de résultat.<br/> - La cotisation est appelée trimestriellement par quart.<br/> + Le calcul de la cotisation est établi une fois par an en début d’année à partir des comptes de résultat du dernier exercice connu, ou du prévisionnel pour les nouveaux adhérents qui n’ont pas encore de compte de résultat.<br + /> + La cotisation est appelée trimestriellement par quart.<br + /> Plancher annuel: 300 € pour les SCOP dont le chiffre d’affaires est inférieur à 100 000 €, 600 € pour les autres. </p> <p class="mt64"> - <strong>COTISATION A LA FEDERATION DES SCOP DE LA COMMUNICATION</strong> + <strong + >COTISATION A LA FEDERATION DES SCOP DE LA COMMUNICATION</strong> </p> <p> - Toutes les coopératives adhérentes de la Confédération Générale des SCOP dont l’objet social se rattache aux secteurs de la communication graphique, audiovisuelle ou multimédia sont concernées.<br/> - L’assiette est la valeur ajoutée de la liasse fiscale ou, si elle n’est pas connue, la valeur ajoutée telle que définie par la Banque de France :<br/> - <i>Valeur ajoutée = total des chiffres d’affaires nets(FL) et subventions d’exploitation(FO) + production stockée(FM) + production immobilisée(FN) - achat de marchandises(FS) - variation de stock marchandises(FT) - achat de matières premières et autres approvisionnements(FU) - variation de stock matières premières et approvisionnements(FV) - autres achats et charges externes(FW)(déduction faite du personnel extérieur et des loyer de crédit - bail) - impôts et taxes(FX)</i> + Toutes les coopératives adhérentes de la Confédération Générale des SCOP dont l’objet social se rattache aux secteurs de la communication graphique, audiovisuelle ou multimédia sont concernées.<br + /> + L’assiette est la valeur ajoutée de la liasse fiscale ou, si elle n’est pas connue, la valeur ajoutée telle que définie par la Banque de France :<br + /> + <i + >Valeur ajoutée = total des chiffres d’affaires nets(FL) et subventions d’exploitation(FO) + production stockée(FM) + production immobilisée(FN) - achat de marchandises(FS) - variation de stock marchandises(FT) - achat de matières premières et autres approvisionnements(FU) - variation de stock matières premières et approvisionnements(FV) - autres achats et charges externes(FW)(déduction faite du personnel extérieur et des loyer de crédit - bail) - impôts et taxes(FX)</i> </p> <p> - Le calcul de la cotisation est établi une fois par an en début d’année à partir des comptes de résultat du dernier exercice connu.<br/> - Taux d’appel de 0,32 %.<br/> - <i>Appel de cotisation trimestriel = (valeur ajoutée x 0,32 %) / 4</i> - Pour les nouvelles coopératives qui n’ont pas encore de compte de résultat: 27 € par trimestre et par salarié.<br/> - Plancher annuel : 108 €<br/> + Le calcul de la cotisation est établi une fois par an en début d’année à partir des comptes de résultat du dernier exercice connu.<br + /> + Taux d’appel de 0,32 %.<br /> + <i + >Appel de cotisation trimestriel = (valeur ajoutée x 0,32 %) / 4</i> + Pour les nouvelles coopératives qui n’ont pas encore de compte de résultat: 27 € par trimestre et par salarié.<br + /> + Plancher annuel : 108 €<br /> Plafond annuel : 18 428 €. </p> </div> @@ -167,22 +273,24 @@ <template id="report_bordereau"> <t t-call="web.html_container"> - <t t-set="docs" t-value="docs.with_context(lang='fr')"/> + <t t-set="docs" t-value="docs.with_context(lang='fr')" /> <t t-foreach="docs" t-as="o"> - <t t-call="cgscop_cotisation_cg.report_bordereau_document" t-lang="fr"/> + <t + t-call="cgscop_cotisation_cg.report_bordereau_document" + t-lang="fr" + /> </t> </t> </template> <!-- QWeb Reports --> - <report - id="cgscop_bordereau_report" - model="scop.bordereau" - string="Bordereau de Cotisation CG" - report_type="qweb-pdf" - name="cgscop_cotisation_cg.report_bordereau" - file="cgscop_cotisation_cg.report_bordereau" - /> + <record id="cgscop_bordereau_report" model="ir.actions.report"> + <field name="name">Bordereau de Cotisation CG</field> + <field name="model">scop.bordereau</field> + <field name="report_type">qweb-pdf</field> + <field name="report_name">cgscop_cotisation_cg.report_bordereau</field> + <field name="report_file">cgscop_cotisation_cg.report_bordereau</field> + </record> </data> </odoo> diff --git a/templates/report_scop_bordereau_payments.xml b/templates/report_scop_bordereau_payments.xml index 15cf0dae4eb3632914966c68e15f02043711a9aa..f66de075d44db0b0fe655f0c2b79288f801eecd4 100644 --- a/templates/report_scop_bordereau_payments.xml +++ b/templates/report_scop_bordereau_payments.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data> @@ -8,62 +8,117 @@ <div class="page" style="font-size: 14px;"> <div class="row"> <div class="col-6 offset-6 mt64 mb64"> - <span t-field="o.partner_id.name" style="text-transform: uppercase; font-weight: 600;"/><br/> - <span t-field="o.partner_id.street" /><br/> - <t t-if="o.partner_id.street2"><span t-field="o.partner_id.street2"/><br/></t> - <t t-if="o.partner_id.street3"><span t-field="o.partner_id.street3"/><br/></t> - <span t-field="o.partner_id.zip" /> <span t-field="o.partner_id.city" style="text-transform: uppercase;"/> - <t t-if="o.partner_id.cedex"> <span t-field="o.partner_id.cedex"/></t> + <span + t-field="o.partner_id.name" + style="text-transform: uppercase; font-weight: 600;" + /><br /> + <span t-field="o.partner_id.street" /><br /> + <t t-if="o.partner_id.street2"><span + t-field="o.partner_id.street2" + /><br /></t> + <t t-if="o.partner_id.street3"><span + t-field="o.partner_id.street3" + /><br /></t> + <span t-field="o.partner_id.zip" /> <span + t-field="o.partner_id.city" + style="text-transform: uppercase;" + /> + <t t-if="o.partner_id.cedex"> <span + t-field="o.partner_id.cedex" + /></t> </div> </div> <div class="row"> <div class="col-12 text-center"> <h2 style="color: #E5074D;"> - Etat des paiements de cotisation <span t-esc="str(o.year)"/> + Etat des paiements de cotisation <span + t-esc="str(o.year)" + /> </h2> </div> </div> <div class="row"> <div class="col-12 mb16"> <p> - N° adhérent : <t t-esc="str(o.partner_id.member_number_int)"/><br/> - Union régionale : <span t-field="o.partner_ur_id.name"/><br/> - N° Bordereau : <span t-field="o.name"/><t t-if="o.is_regul">-<span t-field="o.version"/></t> + N° adhérent : <t + t-esc="str(o.partner_id.member_number_int)" + /><br /> + Union régionale : <span + t-field="o.partner_ur_id.name" + /><br /> + N° Bordereau : <span t-field="o.name" /><t + t-if="o.is_regul" + >-<span t-field="o.version" /></t> </p> </div> </div> <div class="row"> <div class="col-6" style="border: 1px solid #aaa;"> - <div></div> - <h5 class="mt8" style="font-weight: 600;">Cotisations annuelles</h5> + <div /> + <h5 + class="mt8" + style="font-weight: 600;" + >Cotisations annuelles</h5> <p style="font-style: italic; font-size: 13px;"> - <t t-if="o.year_liasse">Calcul basé sur la liasse fiscale + <t + t-if="o.year_liasse" + >Calcul basé sur la liasse fiscale <t t-if="o.is_liasse_previ"> - <span>Prévisionnelle</span><br/> + <span>Prévisionnelle</span><br /> </t> <t t-else=""> - <span t-esc="str(o.year_liasse)" /><br/> + <span t-esc="str(o.year_liasse)" /><br /> </t> </t> - Assiette base <span t-field="o.type_assiette" /> : <span t-field="o.montant_assiette" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" />. + Assiette base <span t-field="o.type_assiette" /> : <span + t-field="o.montant_assiette" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + />. </p> <p> - <t t-set="amount_line" t-value="o.get_contribution_type()" /> + <t + t-set="amount_line" + t-value="o.get_contribution_type()" + /> <table class="table table-sm" style="border: none;"> - <tr t-foreach="amount_line" t-as="line" style="border-bottom: 1px solid #ccc;"> - <td style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('type_contribution_id')[1]"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('amount_total_signed')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <tr + t-foreach="amount_line" + t-as="line" + style="border-bottom: 1px solid #ccc;" + > + <td + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('type_contribution_id')[1]" + /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('amount_total_signed')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </tr> </table> </p> <p> <table class="table table-sm" style="border: none;"> <tr style="border: none"> - <td style="border: none; background: inherit; color: inherit;"> - <strong>Total cotisation annuelle <t t-esc="str(o.year)"/></strong> + <td + style="border: none; background: inherit; color: inherit;" + > + <strong>Total cotisation annuelle <t + t-esc="str(o.year)" + /></strong> </td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"> - <strong></strong><span t-field="o.amount_total_cotiz" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + > + <strong /><span + t-field="o.amount_total_cotiz" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </tr> </table> </p> @@ -71,49 +126,96 @@ <h5 style="font-weight: 600;">Échéancier</h5> <p id="schedule_table_with_payments"> - <t t-set="schedule_line" t-value="o.get_bordereau_move_line_with_payments()" /> - <table class="table table-sm table-striped" style="border: none;"> + <t + t-set="schedule_line" + t-value="o.get_bordereau_move_line_with_payments()" + /> + <table + class="table table-sm table-striped" + style="border: none;" + > <tr> <th>Date d'échéance</th> <th class="text-right">Montant appelé</th> <th class="text-right">Montant dû</th> </tr> - <tr t-foreach="schedule_line.get('plan')" t-as="line" style="border-bottom: 1px solid #ccc;"> + <tr + t-foreach="schedule_line.get('plan')" + t-as="line" + style="border-bottom: 1px solid #ccc;" + > <t t-if="line.get('debit') > 0"> - <td style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('date_maturity:day')"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('debit')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('amount_residual')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <td + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('date_maturity:day')" + /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('debit')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('amount_residual')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </t> </tr> </table> - <table class="table table-sm table-striped" style="border: none;"> + <table + class="table table-sm table-striped" + style="border: none;" + > <tr> <th>Montant dû</th> <th class="text-right">Total appelé</th> <th class="text-right">Total réglé</th> </tr> <tr style="border-bottom: 1px solid #ccc;"> - <td style="border: none; background: inherit; color: inherit;"> - <t t-esc="schedule_line.get('total_residual')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/> + <td + style="border: none; background: inherit; color: inherit;" + > + <t + t-esc="schedule_line.get('total_residual')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /> </td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"> - <t t-esc="schedule_line.get('total_amount')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + > + <t + t-esc="schedule_line.get('total_amount')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /> </td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"> - <t t-esc="schedule_line.get('total_paid')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + > + <t + t-esc="schedule_line.get('total_paid')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /> </td> </tr> </table> </p> <p style="font-size: 13px;"> - <em>IBAN: FR76 4255 9100 0008 0024 8837 710 - BIC : CCOPFRPPXXX</em> + <em + >IBAN: FR76 4255 9100 0008 0024 8837 710 - BIC : CCOPFRPPXXX</em> </p> </div> <div class="col-6" style="margin-top: 220px;"> <div style="border: 1px solid #aaa; padding: 15px;"> - CG Scop <br/> - 30, rue des Epinettes <br/> + CG Scop <br /> + 30, rue des Epinettes <br /> 75017 PARIS </div> </div> @@ -123,25 +225,30 @@ </t> </template> - <template id="report_bordereau_with_payments"> <t t-call="web.html_container"> - <t t-set="docs" t-value="docs.with_context(lang='fr')"/> + <t t-set="docs" t-value="docs.with_context(lang='fr')" /> <t t-foreach="docs" t-as="o"> - <t t-call="cgscop_cotisation_cg.report_bordereau_document_with_payments" t-lang="fr"/> + <t + t-call="cgscop_cotisation_cg.report_bordereau_document_with_payments" + t-lang="fr" + /> </t> </t> </template> <!-- QWeb Reports --> - <report - id="cgscop_bordereau_report_with_payments" - model="scop.bordereau" - string="Etat des paiements" - report_type="qweb-pdf" - name="cgscop_cotisation_cg.report_bordereau_with_payments" - file="cgscop_cotisation_cg.report_bordereau_with_payments" - /> + <record id="cgscop_bordereau_report_with_payments" model="ir.actions.report"> + <field name="name">Etat des paiements</field> + <field name="model">scop.bordereau</field> + <field name="report_type">qweb-pdf</field> + <field + name="report_name" + >cgscop_cotisation_cg.report_bordereau_with_payments</field> + <field + name="report_file" + >cgscop_cotisation_cg.report_bordereau_with_payments</field> + </record> </data> </odoo> diff --git a/templates/report_scop_bordereau_refund.xml b/templates/report_scop_bordereau_refund.xml index 822a22e8dd4c39f9f7fa5445912a770f79b5566c..a0b6c7f198a8bd218b1fe3cb9a4fc12736550c9d 100644 --- a/templates/report_scop_bordereau_refund.xml +++ b/templates/report_scop_bordereau_refund.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data> @@ -8,54 +8,107 @@ <div class="page" style="font-size: 14px;"> <div class="row"> <div class="col-6 offset-6 mt64 mb64"> - <span t-field="o.partner_id.name" style="text-transform: uppercase; font-weight: 600;"/><br/> - <span t-field="o.partner_id.street" /><br/> - <t t-if="o.partner_id.street2"><span t-field="o.partner_id.street2"/><br/></t> - <t t-if="o.partner_id.street3"><span t-field="o.partner_id.street3"/><br/></t> - <span t-field="o.partner_id.zip" /> <span t-field="o.partner_id.city" style="text-transform: uppercase;"/> - <t t-if="o.partner_id.cedex"> <span t-field="o.partner_id.cedex"/></t> + <span + t-field="o.partner_id.name" + style="text-transform: uppercase; font-weight: 600;" + /><br /> + <span t-field="o.partner_id.street" /><br /> + <t t-if="o.partner_id.street2"><span + t-field="o.partner_id.street2" + /><br /></t> + <t t-if="o.partner_id.street3"><span + t-field="o.partner_id.street3" + /><br /></t> + <span t-field="o.partner_id.zip" /> <span + t-field="o.partner_id.city" + style="text-transform: uppercase;" + /> + <t t-if="o.partner_id.cedex"> <span + t-field="o.partner_id.cedex" + /></t> </div> </div> <div class="row"> <div class="col-12 text-center"> <h2 style="color: #E5074D;"> - Avoir sur Appel de cotisation <span t-esc="str(o.year)"/> + Avoir sur Appel de cotisation <span + t-esc="str(o.year)" + /> </h2> </div> </div> <div class="row"> <div class="col-12 mb16"> <p> - Paris, le <span t-esc="o.date_regul" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> + Paris, le <span + t-esc="o.date_regul" + t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}" + /> </p> <p> - N° adhérent : <t t-esc="str(o.partner_id.member_number_int)"/><br/> - Union régionale : <span t-field="o.partner_ur_id.name"/><br/> - N° Bordereau : <span t-field="o.name"/><t t-if="o.is_regul">-<span t-field="o.version"/></t> + N° adhérent : <t + t-esc="str(o.partner_id.member_number_int)" + /><br /> + Union régionale : <span + t-field="o.partner_ur_id.name" + /><br /> + N° Bordereau : <span t-field="o.name" /><t + t-if="o.is_regul" + >-<span t-field="o.version" /></t> </p> </div> </div> <div class="row"> <div class="col-6" style="border: 1px solid #aaa;"> - <div></div> - <h5 class="mt8" style="font-weight: 600;">Cotisations annuelles</h5> + <div /> + <h5 + class="mt8" + style="font-weight: 600;" + >Cotisations annuelles</h5> <p> - <t t-set="amount_line" t-value="o.get_contribution_type_refund()" /> + <t + t-set="amount_line" + t-value="o.get_contribution_type_refund()" + /> <table class="table table-sm" style="border: none;"> - <tr t-foreach="amount_line" t-as="line" style="border-bottom: 1px solid #ccc;"> - <td style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('type_contribution_id')[1]"/></td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"><t t-esc="line.get('amount_total_signed')" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/></td> + <tr + t-foreach="amount_line" + t-as="line" + style="border-bottom: 1px solid #ccc;" + > + <td + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('type_contribution_id')[1]" + /></td> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + ><t + t-esc="line.get('amount_total_signed')" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /></td> </tr> </table> </p> <p> <table class="table table-sm" style="border: none;"> <tr style="border: none"> - <td style="border: none; background: inherit; color: inherit;"> - <strong>Total avoir cotisation annuelle <t t-esc="str(o.year)"/></strong> + <td + style="border: none; background: inherit; color: inherit;" + > + <strong>Total avoir cotisation annuelle <t + t-esc="str(o.year)" + /></strong> </td> - <td class="text-right" style="border: none; background: inherit; color: inherit;"> - <strong></strong><span t-esc="sum(list(map(lambda l: l.get('amount_total_signed'), amount_line)))" t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}"/> + <td + class="text-right" + style="border: none; background: inherit; color: inherit;" + > + <strong /><span + t-esc="sum(list(map(lambda l: l.get('amount_total_signed'), amount_line)))" + t-options="{'widget': 'monetary', 'display_currency': o.company_id.currency_id}" + /> </td> </tr> </table> @@ -66,8 +119,8 @@ <div class="col-6" style="margin-top: 220px;"> <div style="border: 1px solid #aaa; padding: 15px;"> - CG Scop <br/> - 30, rue des Epinettes <br/> + CG Scop <br /> + 30, rue des Epinettes <br /> 75017 PARIS </div> </div> @@ -78,24 +131,28 @@ <template id="report_bordereau_refund"> <t t-call="web.html_container"> - <t t-set="docs" t-value="docs.with_context(lang='fr')"/> + <t t-set="docs" t-value="docs.with_context(lang='fr')" /> <t t-foreach="docs" t-as="o"> - <t t-call="cgscop_cotisation_cg.report_bordereau_document_refund" t-lang="fr"/> + <t + t-call="cgscop_cotisation_cg.report_bordereau_document_refund" + t-lang="fr" + /> </t> </t> </template> - <!-- QWeb Reports --> - <report - id="cgscop_bordereau_report_refund" - model="scop.bordereau" - string="Avoir de Cotisation CG" - report_type="qweb-pdf" - name="cgscop_cotisation_cg.report_bordereau_refund" - file="cgscop_cotisation_cg.report_bordereau_refund" - groups="cgscop_partner.group_cg_administrator" - /> + <record id="cgscop_bordereau_report_refund" model="ir.actions.report"> + <field name="name">Avoir de Cotisation CG</field> + <field name="model">scop.bordereau</field> + <field name="report_type">qweb-pdf</field> + <field + name="report_name" + >cgscop_cotisation_cg.report_bordereau_refund</field> + <field + name="report_file" + >cgscop_cotisation_cg.report_bordereau_refund</field> + </record> </data> </odoo> diff --git a/templates/report_union_sociale.xml b/templates/report_union_sociale.xml index b9ef2d859c653f9b59d57eb0811ca7e48b67153a..1567deea37e49a988994d15a2089b8f0b6991fb3 100644 --- a/templates/report_union_sociale.xml +++ b/templates/report_union_sociale.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <data> @@ -19,91 +19,151 @@ font-size: 9px; } </style> - <t t-if="not o" t-set="o" t-value="doc"/> + <t t-if="not o" t-set="o" t-value="doc" /> <div class="page" style="font-size: 10px;"> <t t-foreach="range(1,5)" t-as="quarter"> - <div id="union-sociale container" class="mt16 m32" style="page-break-inside: avoid;"> - <hr/> + <div + id="union-sociale container" + class="mt16 m32" + style="page-break-inside: avoid;" + > + <hr /> <div class="row"> <div class="col-8"> - <p style="margin-bottom: 0; color: #E5074D; font-weight: bold; font-size: 13px;"> + <p + style="margin-bottom: 0; color: #E5074D; font-weight: bold; font-size: 13px;" + > COTISATION UNION SOCIALE DES SCOP ET DES SCIC - - <t t-esc="quarter"/> + <t t-esc="quarter" /> <t t-if="quarter == 1">er </t> <t t-else="">ème </t> Trimestre - <t t-esc="env.context.get('year', datetime.datetime.now().year)"/> + <t + t-esc="env.context.get('year', datetime.datetime.now().year)" + /> </p> <p><strong><i> L’Union Sociale perçoit directement sa cotisation, merci de lui envoyer un règlement distinct</i></strong></p> <p class="mt16"> - <strong>N° ADHÉRENT : <t t-esc="o.member_number"/></strong> - <br/> - <strong>IDENTITÉ SOCIÉTÉ : <t t-esc="o.name.upper()"/></strong> + <strong>N° ADHÉRENT : <t + t-esc="o.member_number" + /></strong> + <br /> + <strong>IDENTITÉ SOCIÉTÉ : <t + t-esc="o.name.upper()" + /></strong> </p> </div> <div class="col-4"> <div class="text-right" style="font-size: 9px;"> - <img src="/cgscop_cotisation_cg/static/src/img/logo-usscop.png" class="img-fluid" style="max-height: 60px;"/> - <br/> - Tel. : 01 43 07 18 08<br/> - <a href="mailto:contact@union-sociale.coop">contact@union-sociale.coop</a> - <a href="https://www.union-sociale.coop">www.union-sociale.coop</a> + <img + src="/cgscop_cotisation_cg/static/src/img/logo-usscop.png" + class="img-fluid" + style="max-height: 60px;" + /> + <br /> + Tel. : 01 43 07 18 08<br /> + <a + href="mailto:contact@union-sociale.coop" + >contact@union-sociale.coop</a> - <a + href="https://www.union-sociale.coop" + >www.union-sociale.coop</a> </div> </div> </div> <div class="row mt16"> <div class="col-6"> <div> - <p class="presta"><strong>SALAIRES BRUTS</strong> (non plafonnés du trimestre) :</p> - <input type="text" t-attf-name="salaire-{{quarter}}" class="input-empty presta"/> + <p class="presta"><strong + >SALAIRES BRUTS</strong> (non plafonnés du trimestre) :</p> + <input + type="text" + t-attf-name="salaire-{{quarter}}" + class="input-empty presta" + /> </div> <div> <p class="presta"> - - Pour <strong>PRESTABAT</strong> Scop parisiennes du bâtiment et des travaux publics x <strong>0,40</strong> : + - Pour <strong + >PRESTABAT</strong> Scop parisiennes du bâtiment et des travaux publics x <strong + >0,40</strong> : </p> - <input type="text" t-attf-name="prestabat-{{quarter}}" class="input-empty presta"/> + <input + type="text" + t-attf-name="prestabat-{{quarter}}" + class="input-empty presta" + /> </div> <div> <p class="presta"> - - Pour <strong>PRESTASUP</strong> Scop sur le plan national adhérentes à la super section x <strong>0,40</strong> : + - Pour <strong + >PRESTASUP</strong> Scop sur le plan national adhérentes à la super section x <strong + >0,40</strong> : </p> - <input type="text" t-attf-name="prestasup-{{quarter}}" class="input-empty presta"/> + <input + type="text" + t-attf-name="prestasup-{{quarter}}" + class="input-empty presta" + /> </div> <div> <p class="presta"> - - Pour <strong>PRESTA</strong> les autres Scop x <strong>0,30</strong> : + - Pour <strong + >PRESTA</strong> les autres Scop x <strong + >0,30</strong> : </p> - <input type="text" t-attf-name="presta-{{quarter}}" class="input-empty presta"/> + <input + type="text" + t-attf-name="presta-{{quarter}}" + class="input-empty presta" + /> </div> <div> <p class="presta"> - Nombre de salariés à la fin de la période : </p> - <input type="text" t-attf-name="salaries-{{quarter}}" class="input-empty"/> + <input + type="text" + t-attf-name="salaries-{{quarter}}" + class="input-empty" + /> </div> <div> - <p class="presta" style="margin-top: 10px; margin-bottom: 5px; font-size: 11px;"> + <p + class="presta" + style="margin-top: 10px; margin-bottom: 5px; font-size: 11px;" + > <strong> À retourner à l’Union Sociale avant le : <t t-if="quarter != 4"> <t t-if="quarter != 3"> - 15/0<t t-esc="quarter * 3 + 1"/>/<t t-esc="env.context.get('year', datetime.datetime.now().year)"/> + 15/0<t t-esc="quarter * 3 + 1" />/<t + t-esc="env.context.get('year', datetime.datetime.now().year)" + /> </t> <t t-else=""> - 15/<t t-esc="quarter * 3 + 1"/>/<t t-esc="env.context.get('year', datetime.datetime.now().year)"/> + 15/<t t-esc="quarter * 3 + 1" />/<t + t-esc="env.context.get('year', datetime.datetime.now().year)" + /> </t> </t> <t t-else=""> - 15/0<t t-esc="quarter - 3"/>/<t t-esc="env.context.get('year', datetime.datetime.now().year) + 1"/> + 15/0<t t-esc="quarter - 3" />/<t + t-esc="env.context.get('year', datetime.datetime.now().year) + 1" + /> </t> </strong> </p> <div class="row"> - <div class="col-1"><span class="input-block-empty"/></div> + <div class="col-1"><span + class="input-block-empty" + /></div> <!-- <div class="col-1"><input type="checkbox" t-attf-name="cheque-{{quarter}}" class="input-block-empty"/></div>--> <div class="col-5">Chèque</div> - <div class="col-1"><span class="input-block-empty"/></div> + <div class="col-1"><span + class="input-block-empty" + /></div> <!-- <div class="col-1"><input type="checkbox" t-attf-name="vir-{{quarter}}" class="input-block-empty"/></div>--> <div class="col-5">Virement</div> </div> @@ -115,9 +175,11 @@ </div> <div class="col-6"> <div style="padding-top: 70px; "> - <div style="padding: 20px; border: 1px solid #aaa; font-size: 13px;"> - Union sociale des Scop et des Scic<br/> - 61, boulevard de Picpus<br/> + <div + style="padding: 20px; border: 1px solid #aaa; font-size: 13px;" + > + Union sociale des Scop et des Scic<br /> + 61, boulevard de Picpus<br /> 75012 Paris </div> </div> @@ -130,9 +192,12 @@ <template id="report_union_sociale"> <t t-call="web.basic_layout"> - <t t-set="docs" t-value="docs.with_context(lang='fr')"/> + <t t-set="docs" t-value="docs.with_context(lang='fr')" /> <t t-foreach="docs" t-as="o"> - <t t-call="cgscop_cotisation_cg.report_union_sociale_document" t-lang="fr"/> + <t + t-call="cgscop_cotisation_cg.report_union_sociale_document" + t-lang="fr" + /> </t> </t> </template> @@ -145,22 +210,20 @@ <field name="margin_bottom">10</field> <field name="margin_left">10</field> <field name="margin_right">10</field> - <field name="header_line" eval="False"/> + <field name="header_line" eval="False" /> <field name="header_spacing">0</field> <field name="dpi">90</field> </record> <!-- QWeb Reports --> - <report - id="cgscop_union_sociale_report" - model="res.partner" - string="Bordereau Union Sociale" - report_type="qweb-pdf" - name="cgscop_cotisation_cg.report_union_sociale" - file="cgscop_cotisation_cg.report_union_sociale" - paperformat="paperformat_union_sociale" - attachment_use="False" - /> + <record id="cgscop_union_sociale_report" model="ir.actions.report"> + <field name="name">Bordereau Union Sociale</field> + <field name="model">res.partner</field> + <field name="report_type">qweb-pdf</field> + <field name="report_name">cgscop_cotisation_cg.report_union_sociale</field> + <field name="report_file">cgscop_cotisation_cg.report_union_sociale</field> + <field name="paperformat_id" ref="paperformat_union_sociale" /> + </record> </data> </odoo> diff --git a/views/account_invoice.xml b/views/account_invoice.xml deleted file mode 100644 index 0c0150510081e0efb1f5033d705c7fb1d6343f23..0000000000000000000000000000000000000000 --- a/views/account_invoice.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - <data> - - <!-- Form --> - <record id="invoice_form_scop_cg_inherited" model="ir.ui.view"> - <field name="name">account.invoice.form.scop.cg.inherited</field> - <field name="model">account.invoice</field> - <field name="mode">primary</field> - <field name="inherit_id" ref="cgscop_cotisation.invoice_form_scop_inherited"/> - <field name="arch" type="xml"> - - <xpath expr="//header/button[@name='action_invoice_open']" position="attributes"> - <attribute name="states"/> - <attribute name="invisible">1</attribute> - </xpath> - <xpath expr="//header/button[@name='preview_invoice']" position="attributes"> - <attribute name="invisible">True</attribute> - </xpath> - <xpath expr="//header/button[@name='%(account.action_account_invoice_refund)d']" position="attributes"> - <attribute name="invisible">True</attribute> - </xpath> - - <xpath expr="//field[@name='liasse_fiscale_id']" position="replace"> - <group> - <field name="liasse_fiscale_id" readonly="1"/> - <field name="bordereau_id" readonly="1"/> - </group> - <group> - <field name="amount_cg_calculated" readonly="1"/> - <field name="cotiz_quarter" readonly="1"/> - </group> - </xpath> - - <xpath expr="//field[@name='partner_id']" position="attributes"> - <attribute name="readonly">True</attribute> - </xpath> - - <xpath expr="//field[@name='payment_term_id']" position="attributes"> - <attribute name="invisible">1</attribute> - </xpath> - - <xpath expr="//field[@name='date_due']" position="attributes"> - <attribute name="attrs">{'invisible':[('state','=','draft')]}</attribute> - </xpath> - - <xpath expr="//field[@name='payment_mode_id']" position="attributes"> - <attribute name="attrs">{'invisible':[('state','=','draft')]}</attribute> - </xpath> - - </field> - </record> - - <!-- Search --> - <record id="invoice_search_scop_cg_inherited" model="ir.ui.view"> - <field name="name">account.invoice.search.scop.cg.inherited</field> - <field name="model">account.invoice</field> - <field name="priority" eval="25"/> - <field name="mode">primary</field> - <field name="inherit_id" ref="cgscop_cotisation.invoice_search_scop_inherited"/> - <field name="arch" type="xml"> - - <xpath expr="//filter[@name='group_by_partner_id']" position="before"> - <filter name="by_type_cotiz" string="Type de cotisation" context="{'group_by':'type_contribution_id'}"/> - <filter name="by_ur" string="Union régionale" context="{'group_by':'partner_ur_id'}"/> - <separator/> - </xpath> - - </field> - </record> - - <!-- Action --> - <record id="action_scop_cg_appel_cotisation" model="ir.actions.act_window"> - <field name="name">Appels de cotisations</field> - <field name="res_model">account.invoice</field> - <field name="view_mode">tree,form,kanban,calendar,graph,pivot</field> - <field name="domain" eval="[('type','in', ['out_invoice', 'out_refund']), ('is_contribution', '!=', False), ('company_id', '=', ref('base.main_company'))]"/> - <field name="context" eval="{'default_type':'out_invoice', 'type':'out_invoice', 'journal_type': 'sale', 'default_is_contribution': True, 'create': False,}"/> - <field name="search_view_id" ref="invoice_search_scop_cg_inherited"/> - </record> - <record id="action_scop_cg_appel_cotisation_tree" model="ir.actions.act_window.view"> - <field eval="1" name="sequence"/> - <field name="view_mode">tree</field> - <field name="view_id" ref="cgscop_cotisation.invoice_tree_scop_inherited"/> - <field name="act_window_id" ref="action_scop_cg_appel_cotisation"/> - </record> - <record id="action_scop_cg_appel_cotisation_form" model="ir.actions.act_window.view"> - <field eval="2" name="sequence"/> - <field name="view_mode">form</field> - <field name="view_id" ref="invoice_form_scop_cg_inherited"/> - <field name="act_window_id" ref="action_scop_cg_appel_cotisation"/> - </record> - - </data> -</odoo> \ No newline at end of file diff --git a/views/account_move.xml b/views/account_move.xml new file mode 100644 index 0000000000000000000000000000000000000000..7bda03bc25c466a1c9c1d4b59cfbde1c23b23eb2 --- /dev/null +++ b/views/account_move.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="utf-8" ?> +<odoo> + <data> + + <!-- Form --> + <record id="invoice_form_scop_cg_inherited" model="ir.ui.view"> + <field name="name">account.move.form.scop.cg.inherited</field> + <field name="model">account.move</field> + <field name="priority">100</field> + <field name="mode">primary</field> + <field + name="inherit_id" + ref="cgscop_cotisation.account_move_form_scop_inherited" + /> + <field name="arch" type="xml"> + + <xpath + expr="//header/button[@name='action_post']" + position="attributes" + > + <attribute name="states" /> + <attribute name="invisible">1</attribute> + </xpath> + <xpath + expr="//header/button[@name='preview_invoice']" + position="attributes" + > + <attribute name="invisible">True</attribute> + </xpath> + <xpath + expr="//header/button[@name='action_reverse']" + position="attributes" + > + <attribute name="invisible">True</attribute> + </xpath> + + <xpath expr="//field[@name='liasse_fiscale_id']" position="replace"> + <group> + <field name="liasse_fiscale_id" readonly="1" /> + <field name="bordereau_id" readonly="1" /> + </group> + <group> + <field name="amount_cg_calculated" readonly="1" /> + <field name="cotiz_quarter" readonly="1" /> + </group> + </xpath> + + <xpath expr="//field[@name='partner_id']" position="attributes"> + <attribute name="readonly">True</attribute> + </xpath> + + <xpath + expr="//field[@name='invoice_payment_term_id']" + position="attributes" + > + <attribute name="invisible">1</attribute> + </xpath> + + <xpath expr="//field[@name='invoice_date_due']" position="attributes"> + <attribute + name="attrs" + >{'invisible':[('state','=','draft')]}</attribute> + </xpath> + + <xpath expr="//field[@name='payment_mode_id']" position="attributes"> + <attribute + name="attrs" + >{'invisible':[('state','=','draft')]}</attribute> + </xpath> + + </field> + </record> + + <!-- Search --> + <record id="invoice_search_scop_cg_inherited" model="ir.ui.view"> + <field name="name">account.move.search.scop.cg.inherited</field> + <field name="model">account.move</field> + <field name="priority" eval="25" /> + <field name="mode">primary</field> + <field + name="inherit_id" + ref="cgscop_cotisation.account_move_search_scop_inherited" + /> + <field name="arch" type="xml"> + + <xpath expr="//filter[@name='group_by_partner_id']" position="before"> + <filter + name="by_type_cotiz" + string="Type de cotisation" + context="{'group_by':'type_contribution_id'}" + /> + <filter + name="by_ur" + string="Union régionale" + context="{'group_by':'partner_ur_id'}" + /> + <separator /> + </xpath> + + </field> + </record> + + <!-- Action --> + <record id="action_scop_cg_appel_cotisation" model="ir.actions.act_window"> + <field name="name">Appels de cotisations</field> + <field name="res_model">account.move</field> + <field name="view_mode">tree,form,kanban,graph,pivot</field> + <field + name="domain" + eval="[('move_type','in', ['out_invoice', 'out_refund']), ('is_contribution', '!=', False), ('company_id', '=', ref('base.main_company'))]" + /> + <field + name="context" + eval="{'default_mov_type':'out_invoice', 'move_type':'out_invoice', 'journal_type': 'sale', 'default_is_contribution': True, 'create': False,}" + /> + <field name="search_view_id" ref="invoice_search_scop_cg_inherited" /> + </record> + <record + id="action_scop_cg_appel_cotisation_tree" + model="ir.actions.act_window.view" + > + <field eval="1" name="sequence" /> + <field name="view_mode">tree</field> + <field + name="view_id" + ref="cgscop_cotisation.account_move_tree_scop_inherited" + /> + <field name="act_window_id" ref="action_scop_cg_appel_cotisation" /> + </record> + <record + id="action_scop_cg_appel_cotisation_form" + model="ir.actions.act_window.view" + > + <field eval="2" name="sequence" /> + <field name="view_mode">form</field> + <field name="view_id" ref="invoice_form_scop_cg_inherited" /> + <field name="act_window_id" ref="action_scop_cg_appel_cotisation" /> + </record> + + </data> +</odoo> diff --git a/views/menus.xml b/views/menus.xml index cf83ae6744ce629cd8ef5fcbb472b79e762df853..2e3a4348822c89fd78592df7655e9f92e2fc96b5 100644 --- a/views/menus.xml +++ b/views/menus.xml @@ -1,32 +1,39 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2019 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> <!-- MENUS --> - <menuitem id="menu_scop_cotisation_cg_main" - parent="cgscop_cotisation.menu_scop_cotisation" - name="Gestion des cotisations CG Scop" - groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" - sequence="10"/> - <menuitem id="menu_scop_cotisation_cg_calcul" - name="Campagnes de cotisations" - parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" - groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" - action="action_scop_cotisation_cg" - sequence="10"/> - <menuitem name="Bordereaux" - id="scop_bordereau_menu" - parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" - groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" - action="scop_bordereau_act_window" - sequence="20"/> - <menuitem id="menu_scop_cotisation_cg_appel_cotisation" - name="Appels de cotisations" - parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" - groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" - action="action_scop_cg_appel_cotisation" - sequence="30"/> + <menuitem + id="menu_scop_cotisation_cg_main" + parent="cgscop_cotisation.menu_scop_cotisation" + name="Gestion des cotisations CG Scop" + groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" + sequence="10" + /> + <menuitem + id="menu_scop_cotisation_cg_calcul" + name="Campagnes de cotisations" + parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" + groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" + action="action_scop_cotisation_cg" + sequence="10" + /> + <menuitem + name="Bordereaux" + id="scop_bordereau_menu" + parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" + groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" + action="scop_bordereau_act_window" + sequence="20" + /> + <menuitem + id="menu_scop_cotisation_cg_appel_cotisation" + name="Appels de cotisations" + parent="cgscop_cotisation_cg.menu_scop_cotisation_cg_main" + groups="cgscop_cotisation_cg.group_cotisation_cg_administrative" + action="action_scop_cg_appel_cotisation" + sequence="30" + /> </data> </odoo> diff --git a/views/res_config_settings.xml b/views/res_config_settings.xml index 77a1f0e37d6098a871a52e9d6381985ba54d9e09..ee3ebbeccb48bd204aa97ce940c180a8546fcdc3 100644 --- a/views/res_config_settings.xml +++ b/views/res_config_settings.xml @@ -1,70 +1,144 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8" ?> <odoo> <data> <record id="res_config_settings_view_form_cotisations_cg" model="ir.ui.view"> <field name="name">res.config.settings.view.form.inherit.cotisations</field> <field name="model">res.config.settings</field> - <field name="priority" eval="25"/> - <field name="inherit_id" ref="cgscop_cotisation.res_config_settings_view_form_cotisations"/> + <field name="priority" eval="25" /> + <field + name="inherit_id" + ref="cgscop_cotisation.res_config_settings_view_form_cotisations" + /> <field name="arch" type="xml"> <xpath expr="//div[@name='contribution']" position="inside"> - <div class="col-xs-12 col-md-6 o_setting_box" attrs="{'invisible': [('is_contribution', '!=', True)]}"> + <div + class="col-xs-12 col-md-6 o_setting_box" + attrs="{'invisible': [('is_contribution', '!=', True)]}" + > <div class="o_setting_left_pane"> <field name="is_contribution_cg" /> </div> <div class="o_setting_right_pane"> - <label for="is_contribution_cg"/> + <label for="is_contribution_cg" /> <div class="text-muted"> Activer la gestion des cotisations de la CG Scop </div> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_left_pane"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_cg_id"/></div> - <field name="contribution_cg_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <hr + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + /> + <div class="o_setting_left_pane" /> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="contribution_cg_id" /></div> + <field + name="contribution_cg_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_ur_or_fede_journal_id"/></div> - <field name="contribution_ur_or_fede_journal_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <hr + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + /> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="contribution_fede_com_id" /></div> + <field + name="contribution_fede_com_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_fede_com_id"/></div> - <field name="contribution_fede_com_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="journal_fede_com_id" /></div> + <field + name="journal_fede_com_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="receivable_account_fede_com_id"/></div> - <field name="receivable_account_fede_com_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <hr + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + /> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="contribution_fede_cae_id" /></div> + <field + name="contribution_fede_cae_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_fede_cae_id"/></div> - <field name="contribution_fede_cae_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="journal_fede_cae_id" /></div> + <field + name="journal_fede_cae_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="receivable_account_fede_cae_id"/></div> - <field name="receivable_account_fede_cae_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <hr + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + /> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="contribution_hdf_id" /></div> + <field + name="contribution_hdf_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_hdf_id"/></div> - <field name="contribution_hdf_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="journal_ur_hdf_id" /></div> + <field + name="journal_ur_hdf_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="receivable_account_ur_hdf_id"/></div> - <field name="receivable_account_ur_hdf_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <hr + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + /> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="contribution_med_id" /></div> + <field + name="contribution_med_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> - <hr attrs="{'invisible': [('is_contribution_cg', '=', False)]}"/> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="contribution_med_id"/></div> - <field name="contribution_med_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> - </div> - <div class="o_setting_right_pane" attrs="{'invisible': [('is_contribution_cg', '=', False)]}"> - <div><label for="receivable_account_ur_med_id"/></div> - <field name="receivable_account_ur_med_id" options="{'no_open': True, 'no_create': True}" attrs="{'required': [('is_contribution_cg', '=', True)]}"/> + <div + class="o_setting_right_pane" + attrs="{'invisible': [('is_contribution_cg', '=', False)]}" + > + <div><label for="journal_ur_med_id" /></div> + <field + name="journal_ur_med_id" + options="{'no_open': True, 'no_create': True}" + attrs="{'required': [('is_contribution_cg', '=', True)]}" + /> </div> </div> </xpath> @@ -72,4 +146,4 @@ </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/views/scop_bordereau_cg.xml b/views/scop_bordereau_cg.xml index 53c34d8e4c94c843d0d8b894d56010fe6b595090..661365be419cbbc9d9e4ea94181e447ba15b02b9 100644 --- a/views/scop_bordereau_cg.xml +++ b/views/scop_bordereau_cg.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <odoo> @@ -11,155 +11,330 @@ <field name="arch" type="xml"> <form create="false" string="Bordereaux"> <header> - <field name="state" widget="statusbar" clickable="False" readonly="True"/> - <button name="button_validate_bordereau" class="oe_highlight" string="Valider le bordereau" type="object" - states="new" confirm="Confirmer la validation du bordereau ?"/> - <button name="print_bordereau" string="Imprimer" type="object" states="validated,paid"/> - <button name="action_send_email" string="Envoyer par mail" type="object" states="validated"/> - <button name="validate_ongoing_bordereau" class="oe_highlight" string="Valider cette nouvelle version" type="object" states="ongoing"/> - <button name="cancel_ongoing_bordereau" class="oe_highlight" string="Annuler cette nouvelle version" type="object" states="ongoing"/> - <button name="action_change_payment_mode" - class="btn-info" string="Changer le mode de paiement" - type="object" states="ongoing,validated"/> - <button name="%(cgscop_cotisation_cg.scop_cotisation_regul_wizard_act_window)d" - class="btn-warning" - string="Effectuer une Régularisation" - type="action" - states="validated,paid"/> - <button name="%(cgscop_cotisation_cg.scop_bordereau_refund_wizard_act_window)d" - class="btn-warning" - string="Ajouter un avoir" - type="action" - states="ongoing,validated,paid"/> - <button name="%(cgscop_bordereau_report_refund)d" - class="btn-info" - string="Imprimer l'avoir" - type="action" - states="cancel"/> + <field + name="state" + widget="statusbar" + clickable="False" + readonly="True" + /> + <button + name="button_validate_bordereau" + class="oe_highlight" + string="Valider le bordereau" + type="object" + states="new" + confirm="Confirmer la validation du bordereau ?" + /> + <button + name="print_bordereau" + string="Imprimer" + type="object" + states="validated,paid" + /> + <button + name="action_send_email" + string="Envoyer par mail" + type="object" + states="validated" + /> + <button + name="validate_ongoing_bordereau" + class="oe_highlight" + string="Valider cette nouvelle version" + type="object" + states="ongoing" + /> + <button + name="cancel_ongoing_bordereau" + class="oe_highlight" + string="Annuler cette nouvelle version" + type="object" + states="ongoing" + /> + <button + name="action_change_payment_mode" + class="btn-info" + string="Changer le mode de paiement" + type="object" + states="ongoing,validated" + /> + <button + name="%(cgscop_cotisation_cg.scop_cotisation_regul_wizard_act_window)d" + class="btn-warning" + string="Effectuer une Régularisation" + type="action" + states="validated,paid" + /> + <button + name="%(cgscop_cotisation_cg.scop_bordereau_refund_wizard_act_window)d" + class="btn-warning" + string="Ajouter un avoir" + type="action" + states="ongoing,validated,paid" + /> + <button + name="%(cgscop_bordereau_report_refund)d" + class="btn-info" + string="Imprimer l'avoir" + type="action" + states="cancel" + /> </header> <sheet> <div class="oe_button_box" name="button_box"> - <button name="action_show_liasse" type="object" - class="oe_stat_button" icon="fa-bar-chart-o" - attrs="{'invisible':[('liasse_count','=',0)]}"> - <field string="Liasses" name="liasse_count" widget="statinfo"/> + <button + name="action_show_liasse" + type="object" + class="oe_stat_button" + icon="fa-bar-chart-o" + attrs="{'invisible':[('liasse_count','=',0)]}" + > + <field + string="Liasses" + name="liasse_count" + widget="statinfo" + /> </button> - <button name="action_show_cotiz" type="object" - class="oe_stat_button" icon="fa-pencil-square-o" - attrs="{'invisible':[('invoice_count','=',0)]}"> - <field string="Appels" name="invoice_count" widget="statinfo"/> + <button + name="action_show_cotiz" + type="object" + class="oe_stat_button" + icon="fa-pencil-square-o" + attrs="{'invisible':[('invoice_count','=',0)]}" + > + <field + string="Appels" + name="invoice_count" + widget="statinfo" + /> </button> - <button class="oe_stat_button" name="open_payment" - string="Paiements en cours" type="object" - attrs="{'invisible':['|', ('has_outstanding','=',False), ('state', '!=', 'validated')]}" icon="fa-university"/> + <button + class="oe_stat_button" + name="open_payment" + string="Paiements en cours" + type="object" + attrs="{'invisible':['|', ('has_outstanding','=',False), ('state', '!=', 'validated')]}" + icon="fa-university" + /> </div> <div class="oe_title"> <h1> - <field name="name"/> + <field name="name" /> </h1> </div> <h4> - Adhérent : <field name="partner_id"/> <br/> - UR : <field name="partner_ur_id" readonly="True" options="{'no_open': True}"/> + Adhérent : <field name="partner_id" /> <br /> + UR : <field + name="partner_ur_id" + readonly="True" + options="{'no_open': True}" + /> </h4> - <field name="has_outstanding" invisible="1"/> - <div class="alert alert-info mt-3" role="alert" - attrs="{'invisible': ['|', ('has_outstanding','=',False), ('state', '!=', 'validated')]}"> + <field name="has_outstanding" invisible="1" /> + <div + class="alert alert-info mt-3" + role="alert" + attrs="{'invisible': ['|', ('has_outstanding','=',False), ('state', '!=', 'validated')]}" + > Vous avez des paiements en circulation pour ce bordereau. </div> - <div class="alert alert-warning" role="alert" attrs="{'invisible': [('state', '!=', 'ongoing')]}"> - <strong>Bordereau en cours de modification </strong>(Détails dans l'onglet "Historique")<br/> + <div + class="alert alert-warning" + role="alert" + attrs="{'invisible': [('state', '!=', 'ongoing')]}" + > + <strong + >Bordereau en cours de modification </strong>(Détails dans l'onglet "Historique")<br + /> </div> - <field name="is_regul" invisible="1"/> - <div class="alert alert-warning" role="alert" attrs="{'invisible': [('is_regul', '!=', True)]}"> - <strong>Bordereau annulé le : </strong><field name="date_regul" readonly="True"/><br/> - <strong>Motif : </strong><field name="comment_regul" readonly="True"/><br/> - <strong>Nouveau bordereau : </strong><field name="refund_id" readonly="True"/> + <field name="is_regul" invisible="1" /> + <div + class="alert alert-warning" + role="alert" + attrs="{'invisible': [('is_regul', '!=', True)]}" + > + <strong>Bordereau annulé le : </strong><field + name="date_regul" + readonly="True" + /><br /> + <strong>Motif : </strong><field + name="comment_regul" + readonly="True" + /><br /> + <strong>Nouveau bordereau : </strong><field + name="refund_id" + readonly="True" + /> </div> - <div class="alert alert-warning" role="alert" attrs="{'invisible': ['|', ('is_regul', '=', True), ('comment_regul', '=', False)]}"> - <strong>Bordereau version <field name="version" readonly="1"/></strong><br/> - <strong>Modifié le : </strong><field name="date_regul" readonly="True"/><br/> - <strong>Motif : </strong><field name="comment_regul" readonly="True"/><br/> + <div + class="alert alert-warning" + role="alert" + attrs="{'invisible': ['|', ('is_regul', '=', True), ('comment_regul', '=', False)]}" + > + <strong>Bordereau version <field + name="version" + readonly="1" + /></strong><br /> + <strong>Modifié le : </strong><field + name="date_regul" + readonly="True" + /><br /> + <strong>Motif : </strong><field + name="comment_regul" + readonly="True" + /><br /> </div> <group> <group> - <field name="base_cotisation_cg"/> - <field name="date_cotisation" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="payment_mode_id" attrs="{'readonly':[('state','!=','new')]}"/> - <hr/> - <field name="nb_quarter" attrs="{'readonly':[('state','!=','new')]}"/> - <button name="update_bordereau_with_liasse" class="btn" string="Recalculer le bordereau" - confirm="Recalculer les valeurs du bordereau en fonction de la liasse et du nombre de trimestres ?" type="object" states="new"/> + <field name="base_cotisation_cg" /> + <field + name="date_cotisation" + attrs="{'readonly':[('state','!=','new')]}" + /> + <field + name="payment_mode_id" + attrs="{'readonly':[('state','!=','new')]}" + /> + <hr /> + <field + name="nb_quarter" + attrs="{'readonly':[('state','!=','new')]}" + /> + <button + name="update_bordereau_with_liasse" + class="btn" + string="Recalculer le bordereau" + confirm="Recalculer les valeurs du bordereau en fonction de la liasse et du nombre de trimestres ?" + type="object" + states="new" + /> </group> <group> - <span class="oe_grey" attrs="{'invisible': [('liasse_fiscale_id', '!=', False)]}">Pas de liasse fiscale pour le calcul</span> - <field name="liasse_fiscale_id" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}"/> - <field name="year_liasse" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}"/> - <field name="type_liasse_fiscale" options="{'no_open': True}" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}"/> - <button name="action_change_liasse" - class="btn-info mb5" - string="Changer de liasse fiscale" - type="object" - states="new"/> - <br/> - <hr/> - <field name="type_assiette" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}"/> - <field name="montant_assiette" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}"/> - <field name="amount_total_cotiz"/> - <field name="details" nolabel="1"/> + <span + class="oe_grey" + attrs="{'invisible': [('liasse_fiscale_id', '!=', False)]}" + >Pas de liasse fiscale pour le calcul</span> + <field + name="liasse_fiscale_id" + attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}" + /> + <field + name="year_liasse" + attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}" + /> + <field + name="type_liasse_fiscale" + options="{'no_open': True}" + attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}" + /> + <button + name="action_change_liasse" + class="btn-info mb5" + string="Changer de liasse fiscale" + type="object" + states="new" + /> + <br /> + <hr /> + <field + name="type_assiette" + attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}" + /> + <field + name="montant_assiette" + attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}" + /> + <field name="amount_total_cotiz" /> + <field name="details" nolabel="1" /> </group> </group> <notebook> <page string="Appels de cotisation"> - <field name="invoice_ids" widget="one2many" class="mt-2"> - <tree edit="false" create="false" delete="false" default_order="type_contribution_id, cotiz_quarter" - decoration-info="state == 'draft'" decoration-success="state == 'paid'" - decoration-muted="state == 'cancel'" decoration-danger="type == 'out_refund' and state == 'open'"> - <field name="type" invisible="1"/> - <field name="type_contribution_id"/> - <field name="cotiz_quarter"/> - <field name="date_due"/> - <field name="name"/> - <field name="amount_total_signed" string="Montant total" sum="Total"/> - <field name="residual_signed" string="Montant dû" sum="Total"/> - <field name="state"/> - <button name="view_cotiz" string="Afficher" type="object" icon="fa-pencil-square-o"/> + <field + name="invoice_ids" + widget="one2many" + class="mt-2" + > + <tree + edit="false" + create="false" + delete="false" + default_order="type_contribution_id, cotiz_quarter" + decoration-info="state == 'draft'" + decoration-success="state == 'paid'" + decoration-muted="state == 'cancel'" + decoration-danger="move_type == 'out_refund' and state == 'posted'" + > + <field name="move_type" invisible="1" /> + <field name="type_contribution_id" /> + <field name="cotiz_quarter" /> + <field name="invoice_date_due" /> + <field name="name" /> + <field + name="amount_total_signed" + string="Montant total" + sum="Total" + /> + <field + name="amount_residual_signed" + string="Montant dû" + sum="Total" + /> + <field name="state" /> + <button + name="view_cotiz" + string="Afficher" + type="object" + icon="fa-pencil-square-o" + /> </tree> <form> <group> - <field name="type_contribution_id"/> - <field name="cotiz_quarter"/> - <field name="date_due"/> - <field name="name"/> - <field name="amount_cg_calculated"/> - <field name="amount_total_signed"/> - <field name="residual_signed"/> + <field name="type_contribution_id" /> + <field name="cotiz_quarter" /> + <field name="invoice_date_due" /> + <field name="name" /> + <field name="amount_cg_calculated" /> + <field name="amount_total_signed" /> + <field name="amount_residual_signed" /> <field name="nb_quarter" /> - <field name="state"/> + <field name="state" /> </group> </form> </field> </page> <page string="Historique"> - <field name="bordereau_version_ids" widget="one2many" class="mt-2"> - <tree create="false" delete="false" default_order="version desc" editable="top"> - <field name="date"/> - <field name="version"/> - <field name="comment" attrs="{'readonly':[('state','=','validated')]}"/> - <field name="liasse_fiscale_id_old"/> - <field name="type_assiette"/> - <field name="montant_assiette"/> - <field name="amount_total_cotiz"/> - <field name="state" widget="label_selection"/> + <field + name="bordereau_version_ids" + widget="one2many" + class="mt-2" + > + <tree + create="false" + delete="false" + default_order="version desc" + editable="top" + > + <field name="date" /> + <field name="version" /> + <field + name="comment" + attrs="{'readonly':[('state','=','validated')]}" + /> + <field name="liasse_fiscale_id_old" /> + <field name="type_assiette" /> + <field name="montant_assiette" /> + <field name="amount_total_cotiz" /> + <field name="state" widget="label_selection" /> </tree> </field> </page> </notebook> </sheet> <div class="oe_chatter"> - <field name="message_follower_ids" widget="mail_followers"/> - <field name="message_ids" widget="mail_thread"/> + <field name="message_follower_ids" widget="mail_followers" /> + <field name="message_ids" widget="mail_thread" /> </div> </form> </field> @@ -170,16 +345,20 @@ <field name="name">scop.bordereau.tree</field> <field name="model">scop.bordereau</field> <field name="arch" type="xml"> - <tree decoration-info="state == 'new'" create="false" string="Bordereaux"> - <field name="member_number"/> - <field name="partner_id"/> - <field name="partner_ur_id"/> - <field name="year"/> - <field name="state"/> - <field name="type_assiette"/> - <field name="montant_assiette"/> - <field name="amount_total_cotiz" sum="Total"/> - <field name="amount_residual" sum="Total"/> + <tree + decoration-info="state == 'new'" + create="false" + string="Bordereaux" + > + <field name="member_number" /> + <field name="partner_id" /> + <field name="partner_ur_id" /> + <field name="year" /> + <field name="state" /> + <field name="type_assiette" /> + <field name="montant_assiette" /> + <field name="amount_total_cotiz" sum="Total" /> + <field name="amount_residual" sum="Total" /> </tree> </field> </record> @@ -190,42 +369,100 @@ <field name="model">scop.bordereau</field> <field name="arch" type="xml"> <search string="Bordereaux"> - <field name="partner_id" string="Adhérent"/> - <field name="member_number" string="N° Adhérent"/> - <field name="name" string="Référence du bordereau"/> - <field name="year" string="Année de cotisation"/> - <filter name="state_new" string="Brouillon" - domain="[('state', '=', 'new')]"/> - <filter name="state_ongoing" string="En cours de modification" - domain="[('state', '=', 'ongoing')]"/> - <filter name="state_validated" string="Validé" - domain="[('state', '=', 'validated')]"/> - <filter name="state_paid" string="Payé" - domain="[('state', '=', 'paid')]"/> - <filter name="has_outstanding" string="Paiements en cours" - domain="[('has_outstanding', '=', True)]"/> - <separator/> - <filter name="current_year" string="Campagne année en cours" - domain="[('year', '=', (context_today()).strftime('%Y'))]"/> - <filter name="previous_year" string="Campagne année précédente" - domain="[('year', '=', (context_today()-datetime.timedelta(weeks=52)).strftime('%Y'))]"/> - <filter name="next_year" string="Campagne année suivante" - domain="[('year', '=', (context_today()+datetime.timedelta(weeks=52)).strftime('%Y'))]"/> - <separator/> - <filter name="bordereau_without_liasse" string="Pas de liasse de référence" - domain="[('liasse_fiscale_id', '=', False)]"/> - <filter name="assiette_equals_zero" string="Assiette(s) égale(s) à zéro" - domain="[('montant_assiette', '=', 0)]"/> - <separator/> - <filter name="4_quarter" string="Sur 4 trimestres" domain="[('nb_quarter', '=', '4')]"/> - <filter name="3_quarter" string="Sur 3 trimestres" domain="[('nb_quarter', '=', '3')]"/> - <filter name="2_quarter" string="Sur 2 trimestres" domain="[('nb_quarter', '=', '2')]"/> - <filter name="1_quarter" string="Sur 1 trimestre" domain="[('nb_quarter', '=', '1')]"/> - <separator/> - <filter name="is_ca" string="Assiette CA" domain="[('type_assiette', '=', 'ca')]"/> - <filter name="is_va" string="Assiette VA" domain="[('type_assiette', '=', 'va')]"/> + <field name="partner_id" string="Adhérent" /> + <field name="member_number" string="N° Adhérent" /> + <field name="name" string="Référence du bordereau" /> + <field name="year" string="Année de cotisation" /> + <filter + name="state_new" + string="Brouillon" + domain="[('state', '=', 'new')]" + /> + <filter + name="state_ongoing" + string="En cours de modification" + domain="[('state', '=', 'ongoing')]" + /> + <filter + name="state_validated" + string="Validé" + domain="[('state', '=', 'validated')]" + /> + <filter + name="state_paid" + string="Payé" + domain="[('state', '=', 'paid')]" + /> + <filter + name="has_outstanding" + string="Paiements en cours" + domain="[('has_outstanding', '=', True)]" + /> + <separator /> + <filter + name="current_year" + string="Campagne année en cours" + domain="[('year', '=', (context_today()).strftime('%Y'))]" + /> + <filter + name="previous_year" + string="Campagne année précédente" + domain="[('year', '=', (context_today()-datetime.timedelta(weeks=52)).strftime('%Y'))]" + /> + <filter + name="next_year" + string="Campagne année suivante" + domain="[('year', '=', (context_today()+datetime.timedelta(weeks=52)).strftime('%Y'))]" + /> + <separator /> + <filter + name="bordereau_without_liasse" + string="Pas de liasse de référence" + domain="[('liasse_fiscale_id', '=', False)]" + /> + <filter + name="assiette_equals_zero" + string="Assiette(s) égale(s) à zéro" + domain="[('montant_assiette', '=', 0)]" + /> + <separator /> + <filter + name="4_quarter" + string="Sur 4 trimestres" + domain="[('nb_quarter', '=', '4')]" + /> + <filter + name="3_quarter" + string="Sur 3 trimestres" + domain="[('nb_quarter', '=', '3')]" + /> + <filter + name="2_quarter" + string="Sur 2 trimestres" + domain="[('nb_quarter', '=', '2')]" + /> + <filter + name="1_quarter" + string="Sur 1 trimestre" + domain="[('nb_quarter', '=', '1')]" + /> + <separator /> + <filter + name="is_ca" + string="Assiette CA" + domain="[('type_assiette', '=', 'ca')]" + /> + <filter + name="is_va" + string="Assiette VA" + domain="[('type_assiette', '=', 'va')]" + /> <group string="Group By"> - <filter name="by_year" string="Année de cotisation" context="{'group_by':'year'}"/> + <filter + name="by_year" + string="Année de cotisation" + context="{'group_by':'year'}" + /> </group> </search> </field> @@ -241,4 +478,4 @@ </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/views/scop_cotisation_cg.xml b/views/scop_cotisation_cg.xml index cead779d9a90cf06c42c96b83fe29ead09f74f41..552baeb226414b96594bce3120ecc6ea827e7b6e 100644 --- a/views/scop_cotisation_cg.xml +++ b/views/scop_cotisation_cg.xml @@ -1,7 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2019 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> @@ -11,12 +10,12 @@ <field name="model">scop.cotisation.cg</field> <field name="arch" type="xml"> <tree string="Cotisations"> - <field name="year"/> - <field name="name"/> - <field name="create_date"/> - <field name="state"/> - <field name="member_count"/> - <field name="write_date"/> + <field name="year" /> + <field name="name" /> + <field name="create_date" /> + <field name="state" /> + <field name="member_count" /> + <field name="write_date" /> </tree> </field> </record> @@ -28,50 +27,105 @@ <field name="arch" type="xml"> <form string="Cotisations"> <header> - <button name="bordereaux_view" type="object" string="Voir les bordereaux"/> - <button name="cotiz_view" type="object" string="Voir les appels de cotisations"/> - <button name="cotiz_generate" type="object" string="Calculer les cotisatisons de renouvellement" class="oe_highlight" states="new,ongoing"/> - <button name="cotiz_generate_wizard" type="object" string="Calculer les cotisatisons des nouveaux adhérents" class="oe_highlight" states="new,ongoing"/> - <button name="bordereau_validate" type="object" string="Valider les bordereaux" class="oe_highlight" - states="new,ongoing" confirm="Les bordereaux validés ne pourront plus être remis en brouillon"/> - <field name="state" widget="statusbar" clickable="False"/> + <button + name="bordereaux_view" + type="object" + string="Voir les bordereaux" + /> + <button + name="cotiz_view" + type="object" + string="Voir les appels de cotisations" + /> + <button + name="cotiz_generate" + type="object" + string="Calculer les cotisations de renouvellement" + class="oe_highlight" + states="new,ongoing" + /> + <button + name="cotiz_generate_wizard" + type="object" + string="Calculer les cotisatisons des nouveaux adhérents" + class="oe_highlight" + states="new,ongoing" + /> + <button + name="bordereau_validate" + type="object" + string="Valider les bordereaux" + class="oe_highlight" + states="new,ongoing" + confirm="Les bordereaux validés ne pourront plus être remis en brouillon" + /> + <field name="state" widget="statusbar" clickable="False" /> </header> <sheet> - <h1><field name="name"/></h1> + <h1><field name="name" /></h1> <group> <group name="contribution" string="Cotisations"> - <field name="year"/> - <field name="date_cotisation" attrs="{'readonly': [('state', '!=', 'new')], 'required': [('state', '!=', 'new')]}"/> - <field name="create_date"/> - <field name="write_date"/> + <field name="year" /> + <field + name="date_cotisation" + attrs="{'readonly': [('state', '!=', 'new')], 'required': [('state', '!=', 'new')]}" + /> + <field name="create_date" /> + <field name="write_date" /> </group> <group name="count_contribution" string="Adhérents"> - <field name="member_count" readonly="1"/> - <field name="new_member_count" readonly="1"/> - <field name="invoice_count" readonly="1"/> - <field name="invoice_valid_count" readonly="1"/> + <field name="member_count" readonly="1" /> + <field name="new_member_count" readonly="1" /> + <field name="invoice_count" readonly="1" /> + <field name="invoice_valid_count" readonly="1" /> </group> </group> <group> <group name="schedule" string="Échéancier"> - <field name="trimester_1" attrs="{'required': [('state', '!=', 'new')]}"/> - <field name="trimester_2" attrs="{'required': [('state', '!=', 'new')]}"/> - <field name="trimester_3" attrs="{'required': [('state', '!=', 'new')]}"/> - <field name="trimester_4" attrs="{'required': [('state', '!=', 'new')]}"/> + <field + name="trimester_1" + attrs="{'required': [('state', '!=', 'new')]}" + /> + <field + name="trimester_2" + attrs="{'required': [('state', '!=', 'new')]}" + /> + <field + name="trimester_3" + attrs="{'required': [('state', '!=', 'new')]}" + /> + <field + name="trimester_4" + attrs="{'required': [('state', '!=', 'new')]}" + /> </group> </group> <notebook> <page name="simulation" string="Simulations"> - <h5 attrs="{'invisible': [('state', '!=', 'new')]}">Ajouter une simulation :</h5> - <hr attrs="{'invisible': [('state', '!=', 'new')]}"/> - <button name="add_simul" class="btn btn-outline-info" style="margin-right: 20px; width: 250px;" - type="object" string="Globale : CG, UR et Fédération" - attrs="{'invisible': [('state', '!=', 'new')]}" context="{'type_simul': 'all'}"/> + <h5 + attrs="{'invisible': [('state', '!=', 'new')]}" + >Ajouter une simulation :</h5> + <hr attrs="{'invisible': [('state', '!=', 'new')]}" /> + <button + name="add_simul" + class="btn btn-outline-info" + style="margin-right: 20px; width: 250px;" + type="object" + string="Globale : CG, UR et Fédération" + attrs="{'invisible': [('state', '!=', 'new')]}" + context="{'type_simul': 'all'}" + /> - <button name="add_simul" class="btn btn-outline-info" style="width: 250px;" - type="object" string="CG Scop uniquement" - attrs="{'invisible': [('state', '!=', 'new')]}" context="{'type_simul': 'cgscop'}"/> - <field name="simul_ids" mode="tree"/> + <button + name="add_simul" + class="btn btn-outline-info" + style="width: 250px;" + type="object" + string="CG Scop uniquement" + attrs="{'invisible': [('state', '!=', 'new')]}" + context="{'type_simul': 'cgscop'}" + /> + <field name="simul_ids" mode="tree" /> </page> </notebook> </sheet> @@ -84,38 +138,62 @@ <field name="name">scop.cotisation.cg.kanban</field> <field name="model">scop.cotisation.cg</field> <field name="arch" type="xml"> - <kanban class="oe_background_grey o_kanban_dashboard o_account_kanban" default_order="year desc"> - <field name="name"/> - <field name="year"/> - <field name="state"/> - <field name="member_count"/> - <field name="new_member_count"/> - <field name="percent_cotiz_paid"/> - <field name="graph_values"/> - <field name="amount_called"/> - <field name="amount_paid"/> - <field name="amount_residual"/> + <kanban + class="oe_background_grey o_kanban_dashboard o_account_kanban" + default_order="year desc" + > + <field name="name" /> + <field name="year" /> + <field name="state" /> + <field name="member_count" /> + <field name="new_member_count" /> + <field name="percent_cotiz_paid" /> + <field name="graph_values" /> + <field name="amount_called" /> + <field name="amount_paid" /> + <field name="amount_residual" /> <templates> <t t-name="kanban-box"> - <div class="container o_kanban_card_content oe_kanban_global_click"> + <div + class="container o_kanban_card_content oe_kanban_global_click" + > <div class="row"> <div class="col"> - <h2 class="mt16"><field name="name"/></h2> - <hr/> + <h2 class="mt16"><field name="name" /></h2> + <hr /> <t> <p class="text-muted"> - Nombre d'adhérents renouvelés : <field name="member_count"/> <br /> - Nombre de nouveaux adhérents : <field name="new_member_count"/> <br /> + Nombre d'adhérents renouvelés : <field + name="member_count" + /> <br /> + Nombre de nouveaux adhérents : <field + name="new_member_count" + /> <br /> </p> </t> </div> </div> <div class="row"> <div class="col-6 text-center"> - <field name="percent_cotiz_paid" widget="gauge"/> - <div class="btn-group-vertical"> - <button type="object" name="cotiz_view" class="btn btn-info">Voir les appels <br /> de cotisations</button> - <button type="object" name="bordereaux_view" class="btn btn-info">Voir les bordereaux</button> + <field + name="percent_cotiz_paid" + widget="gauge" + /> + <div + class="btn-group btn-group-vertical" + role="group" + > + <button + type="object" + name="cotiz_view" + class="btn btn-info" + >Voir les appels <br + /> de cotisations</button> + <button + type="object" + name="bordereaux_view" + class="btn btn-info" + >Voir les bordereaux</button> </div> </div> <div class="col-6"> @@ -123,21 +201,31 @@ <tbody> <tr> <td>Montant appelé</td> - <td><field name="amount_called"/> €</td> + <td><field + name="amount_called" + /> €</td> </tr> <tr> <td>Montant réglé</td> - <td><field name="amount_paid"/> €</td> + <td><field + name="amount_paid" + /> €</td> </tr> <tr> <td>Montant à percevoir</td> - <td><field name="amount_residual"/> €</td> + <td><field + name="amount_residual" + /> €</td> </tr> </tbody> </table> </div> <div> - <field name="graph_values" widget="dashboard_graph" graph_type="bar"/> + <field + name="graph_values" + widget="dashboard_graph" + graph_type="bar" + /> </div> </div> </div> diff --git a/views/scop_cotisation_simulation.xml b/views/scop_cotisation_simulation.xml index 57e73ed4ea058e489ccb5df9325413c7fa9b3417..103d947ddea431ec2986836cf1b30b1596ba66b0 100644 --- a/views/scop_cotisation_simulation.xml +++ b/views/scop_cotisation_simulation.xml @@ -1,7 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2019 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> @@ -11,16 +10,21 @@ <field name="model">scop.cotisation.cg.simulation</field> <field name="arch" type="xml"> <tree string="Simulations" create="0" edit="0"> - <field name="create_date" string="Date de création"/> - <field name="type_simul"/> + <field name="create_date" string="Date de création" /> + <field name="type_simul" /> <field name="file" /> - <field name="total_member"/> - <field name="total_cg"/> - <field name="total_hdf"/> - <field name="total_med"/> - <field name="total_com"/> - <field name="total_cae"/> - <button name="get_simul_file" type="object" string="Télécharger la simulation" class="btn btn-sm btn-outline-info"/> + <field name="total_member" /> + <field name="total_cg" /> + <field name="total_hdf" /> + <field name="total_med" /> + <field name="total_com" /> + <field name="total_cae" /> + <button + name="get_simul_file" + type="object" + string="Télécharger la simulation" + class="btn btn-sm btn-outline-info" + /> </tree> </field> </record> @@ -34,17 +38,23 @@ <sheet> <group> <group string="Fichier simulation"> - <field name="create_date" string="Date de création"/> - <field name="type_simul" readonly="1"/> - <button name="get_simul_file" type="object" icon="fa-download" string="Télécharger la simulation" class="btn btn-sm btn-outline-info"/> + <field name="create_date" string="Date de création" /> + <field name="type_simul" readonly="1" /> + <button + name="get_simul_file" + type="object" + icon="fa-download" + string="Télécharger la simulation" + class="btn btn-sm btn-outline-info" + /> </group> <group string="Données globales"> - <field name="total_member" readonly="1"/> - <field name="total_cg" readonly="1"/> - <field name="total_hdf" readonly="1"/> - <field name="total_med" readonly="1"/> - <field name="total_com" readonly="1"/> - <field name="total_cae" readonly="1"/> + <field name="total_member" readonly="1" /> + <field name="total_cg" readonly="1" /> + <field name="total_hdf" readonly="1" /> + <field name="total_med" readonly="1" /> + <field name="total_com" readonly="1" /> + <field name="total_cae" readonly="1" /> </group> </group> </sheet> @@ -53,7 +63,10 @@ </record> - <record id="view_scop_cotisation_cg_simulation_action" model="ir.actions.act_window"> + <record + id="view_scop_cotisation_cg_simulation_action" + model="ir.actions.act_window" + > <field name="name">Simulation Cotisation</field> <field name="type">ir.actions.act_window</field> <field name="res_model">scop.cotisation.cg.simulation</field> diff --git a/views/scop_liasse_fiscale.xml b/views/scop_liasse_fiscale.xml index c9556bfa0e116c32c3e88156cf663dbc2e1cc850..4781e3426aa6c4b2b7cb99bdf72297ae32105357 100644 --- a/views/scop_liasse_fiscale.xml +++ b/views/scop_liasse_fiscale.xml @@ -1,7 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> @@ -9,25 +8,43 @@ <record id="view_scop_liasse_fiscale_simulation_form" model="ir.ui.view"> <field name="name">scop.liasse.fiscale.contribution.form</field> <field name="model">scop.liasse.fiscale</field> - <field name="inherit_id" ref="cgscop_liste_ministere.scop_liasse_fiscale_form_view_prio"/> + <field + name="inherit_id" + ref="cgscop_liasse_fiscale.scop_liasse_fiscale_form_view_prio" + /> <field name="arch" type="xml"> <xpath expr="//form" position="inside"> - <hr/> + <hr /> <div class="alert alert-info" role="alert"> - <strong><u>Cotisations théoriques</u></strong><br/> + <strong><u>Cotisations théoriques</u></strong><br /> Cette section donne les montants théoriques des diverses cotisations en fonction des valeurs de la liasse fiscale. </div> <group name="simulation"> <group> - <field name="contribution_base_type" string="Type Assiette"/> - <field name="contribution_base_amount" string="Montant Assiette"/> - <field name="contribution_cg" string="Cotisation CG Scop"/> + <field + name="contribution_base_type" + string="Type Assiette" + /> + <field + name="contribution_base_amount" + string="Montant Assiette" + /> + <field name="contribution_cg" string="Cotisation CG Scop" /> </group> <group> - <field name="contribution_hdf" string="Cotisation HDF"/> - <field name="contribution_med" string="Cotisation Méditerranée"/> - <field name="contribution_com" string="Cotisation Fédération Com"/> - <field name="contribution_cae" string="Cotisation Fédération CAE"/> + <field name="contribution_hdf" string="Cotisation HDF" /> + <field + name="contribution_med" + string="Cotisation Méditerranée" + /> + <field + name="contribution_com" + string="Cotisation Fédération Com" + /> + <field + name="contribution_cae" + string="Cotisation Fédération CAE" + /> </group> </group> </xpath> diff --git a/wizard/__init__.py b/wizard/__init__.py index a23c4c181537020603c1172196a3bd075001c6b0..be42db43bb3b2da4b97807fb4480647a78fefbe6 100644 --- a/wizard/__init__.py +++ b/wizard/__init__.py @@ -1,7 +1,7 @@ # © 2020 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import account_invoice_refund +from . import account_move_reversal from . import export_journal_wizard from . import scop_bordereau_update_liasse_wizard from . import scop_bordereau_payment_mode_wizard diff --git a/wizard/account_invoice_refund.py b/wizard/account_invoice_refund.py deleted file mode 100644 index 489b288c5f8da9dae4b7c284d8572970a9eb79c8..0000000000000000000000000000000000000000 --- a/wizard/account_invoice_refund.py +++ /dev/null @@ -1,24 +0,0 @@ -# © 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, api - - -class ContributionCgAccountInvoiceRefund(models.TransientModel): - _inherit = 'account.invoice.refund' - - def _get_refund(self, inv, mode): - """ - Surcharge la la fonction initiale pour ajouter l'id - de la base de cotisation cg - :param inv: facture - :param mode: wizard mode - :return: avoir - """ - refund = super( - ContributionCgAccountInvoiceRefund, self)._get_refund(inv, mode) - refund.update({ - 'cotisation_cg_id': inv.cotisation_cg_id.id, - 'bordereau_id': inv.bordereau_id.id, - }) - return refund diff --git a/wizard/account_move_reversal.py b/wizard/account_move_reversal.py new file mode 100644 index 0000000000000000000000000000000000000000..89eee4f0569867e90f47004fda0bb51ed365f6a2 --- /dev/null +++ b/wizard/account_move_reversal.py @@ -0,0 +1,25 @@ +# © 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 + + +class AccountMoveReversal(models.TransientModel): + _inherit = "account.move.reversal" + + def _prepare_default_reversal(self, move): + """ + Surcharge la la fonction initiale pour ajouter l'id + de la base de cotisation cg + :param inv: facture + :param mode: wizard mode + :return: avoir + """ + refund = super(AccountMoveReversal, self)._prepare_default_reversal(move) + refund.update( + { + "cotisation_cg_id": move.cotisation_cg_id.id, + "bordereau_id": move.bordereau_id.id, + } + ) + return refund diff --git a/wizard/export_journal_wizard.py b/wizard/export_journal_wizard.py old mode 100755 new mode 100644 index 6cb84ae5931fafdba649ead3a6c54e3b21878501..62c1c4e7e0656d77a2b0f5ee160b46a17e202532 --- a/wizard/export_journal_wizard.py +++ b/wizard/export_journal_wizard.py @@ -3,7 +3,7 @@ from urllib.parse import urlencode -from odoo import models, fields, api +from odoo import api, fields, models class ExportJournalWizard(models.TransientModel): @@ -16,30 +16,33 @@ class ExportJournalWizard(models.TransientModel): @api.model def _get_default_export(self): - export = self.env['export.journal.type'].search([ - ('company_id', '=', self.env.user.company_id.id)], limit=1) + export = self.env["export.journal.type"].search( + [("company_id", "=", self.env.user.company_id.id)], limit=1 + ) return export - date_start = fields.Date('Date de début des écritures') - date_end = fields.Date( - string='Date de fin des écritures') + date_start = fields.Date("Date de début des écritures") + date_end = fields.Date(string="Date de fin des écritures") - date_creation_start = fields.Date('Date de début (création des écritures)') - date_creation_end = fields.Date( - string='Date de fin (création des écritures)') + date_creation_start = fields.Date("Date de début (création des écritures)") + date_creation_end = fields.Date(string="Date de fin (création des écritures)") company_id = fields.Many2one( - comodel_name='res.company', - default=_get_default_company + comodel_name="res.company", default=_get_default_company ) partner_ids = fields.Many2many( - comodel_name='res.partner', - string='Coopératives', - domain=[('is_cooperative', '=', True)] + comodel_name="res.partner", + string="Coopératives", + domain=[("is_cooperative", "=", True)], ) export_type = fields.Selection( - [('empty', 'Ecritures non exportées'), ('all', 'Toutes les écritures')], - string='Ecritures à exporter', default="empty") + [ + ("empty", "Ecritures non exportées"), + ("all", "Toutes les écritures"), + ], + string="Ecritures à exporter", + default="empty", + ) def get_cg_export(self): """ @@ -47,23 +50,27 @@ class ExportJournalWizard(models.TransientModel): :return: ir.actions.act_url """ datas = { - 'export_type': self.export_type, - 'company_id': self.company_id.id, + "export_type": self.export_type, + "company_id": self.company_id.id, } if self.date_start and self.date_end: - datas.update({ - 'date_start': self.date_start, - 'date_end': self.date_end, - }) + datas.update( + { + "date_start": self.date_start, + "date_end": self.date_end, + } + ) if self.date_creation_start and self.date_creation_end: - datas.update({ - 'date_creation_start': self.date_creation_start, - 'date_creation_end': self.date_creation_end, - }) + datas.update( + { + "date_creation_start": self.date_creation_start, + "date_creation_end": self.date_creation_end, + } + ) if self.partner_ids: - datas['partner_ids'] = ','.join(str(x) for x in self.partner_ids.ids) + datas["partner_ids"] = ",".join(str(x) for x in self.partner_ids.ids) return { - 'type': 'ir.actions.act_url', - 'url': '/web/export_journal_cg?' + urlencode(datas), - 'target': 'new', + "type": "ir.actions.act_url", + "url": "/web/export_journal_cg?" + urlencode(datas), + "target": "new", } diff --git a/wizard/export_journal_wizard_view.xml b/wizard/export_journal_wizard_view.xml old mode 100755 new mode 100644 index 4ec116560ac2c960ce25ffaf2b128f5d7a7fc5c9..e1ec98f1e591366c7e573f40827738614f135251 --- a/wizard/export_journal_wizard_view.xml +++ b/wizard/export_journal_wizard_view.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8" ?> <odoo> <record id="data_export_cg_view_form" model="ir.ui.view"> <field name="name">export.journal.cg.wizard.form</field> @@ -7,40 +7,72 @@ <form string="Export des données"> <group> <group> - <field name="company_id" invisible="True"/> + <field name="company_id" invisible="True" /> <field name="export_type" widget="radio" /> </group> </group> - <p class="text-muted">Les dates de début et de fin sont incluses dans l'export des écritures</p> - <hr/> - <p style="background: #f0f0f0; padding: 5px"><u>Sélection sur la plage de <strong>date d'écriture</strong> :</u></p> + <p + class="text-muted" + >Les dates de début et de fin sont incluses dans l'export des écritures</p> + <hr /> + <p style="background: #f0f0f0; padding: 5px"><u + >Sélection sur la plage de <strong + >date d'écriture</strong> :</u></p> <group name="date"> <group> - <field name="date_start" attrs="{'required': [('date_end', '!=', False)]}"/> + <field + name="date_start" + attrs="{'required': [('date_end', '!=', False)]}" + /> </group> <group> - <field name="date_end" attrs="{'required': [('date_start', '!=', False)]}"/> + <field + name="date_end" + attrs="{'required': [('date_start', '!=', False)]}" + /> </group> </group> - <hr/> - <p style="background: #f0f0f0; padding: 5px"><u>Sélection sur la plage de <strong>date de création de l'écriture</strong> :</u></p> + <hr /> + <p style="background: #f0f0f0; padding: 5px"><u + >Sélection sur la plage de <strong + >date de création de l'écriture</strong> :</u></p> <group name="date"> <group> - <field name="date_creation_start" attrs="{'required': [('date_creation_end', '!=', False)]}"/> + <field + name="date_creation_start" + attrs="{'required': [('date_creation_end', '!=', False)]}" + /> </group> <group> - <field name="date_creation_end" attrs="{'required': [('date_creation_start', '!=', False)]}"/> + <field + name="date_creation_end" + attrs="{'required': [('date_creation_start', '!=', False)]}" + /> </group> </group> - <hr/> - <p style="background: #f0f0f0; padding: 5px"><u>Sélection des coopératives (si souhaité) :</u></p> + <hr /> + <p style="background: #f0f0f0; padding: 5px"><u + >Sélection des coopératives (si souhaité) :</u></p> <group> - <field name="partner_ids" widget="many2many_tags" options="{'no_create': True, 'no_edit': True}"/> + <field + name="partner_ids" + widget="many2many_tags" + options="{'no_create': True, 'no_edit': True}" + /> </group> <footer> - <button class="btn btn-sm btn-primary" name="get_cg_export" string="Télécharger" type="object"/> - <button class="btn btn-sm btn-default" special="cancel" string="Fermer"/> + <button + class="btn btn-sm btn-primary" + name="get_cg_export" + string="Télécharger" + type="object" + /> + <button + class="btn btn-sm btn-default" + special="cancel" + string="Fermer" + /> </footer> </form> </field> @@ -51,9 +83,15 @@ <field name="type">ir.actions.act_window</field> <field name="res_model">export.journal.cg.wizard</field> <field name="view_mode">form</field> - <field name="view_id" ref="data_export_cg_view_form"/> + <field name="view_id" ref="data_export_cg_view_form" /> <field name="target">new</field> </record> - <menuitem action="data_export_cg_action" id="menu_data_export_cg" name="Export Journal CG Scop" parent="account.menu_finance_entries" sequence="0" /> + <menuitem + action="data_export_cg_action" + id="menu_data_export_cg" + name="Export Journal CG Scop" + parent="account.menu_finance_entries" + sequence="0" + /> </odoo> diff --git a/wizard/scop_bordereau_payment_mode_wizard.py b/wizard/scop_bordereau_payment_mode_wizard.py index 45efe0ab20b24c13e42fc35a59855c52e588cedf..7f8ee13ca66298dcd333f7a7c319f231d8e553a4 100644 --- a/wizard/scop_bordereau_payment_mode_wizard.py +++ b/wizard/scop_bordereau_payment_mode_wizard.py @@ -1,28 +1,34 @@ # Copyright 2021 Le Filament # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models, api +from odoo import fields, models class ScopBordereauChangePaymentMode(models.TransientModel): - _name = 'scop.bordereau.change.payment.mode.wizard' - _description = 'Changement de mode de paiement' + _name = "scop.bordereau.change.payment.mode.wizard" + _description = "Changement de mode de paiement" bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau', + comodel_name="scop.bordereau", + string="Bordereau", readonly=True, ) payment_mode_id = fields.Many2one( - comodel_name='account.payment.mode', - string="Nouveau mode de paiment",) + comodel_name="account.payment.mode", + string="Nouveau mode de paiment", + ) change_type = fields.Selection( - string='Type d\'affectation', - selection=[('punctual', 'Définir pour les échéances non payées de ce ' - 'bordereau uniquement'), - ('all', 'Définir pour toutes les prochaines échéances')], - default='punctual', - required=False, ) + string="Type d'affectation", + selection=[ + ( + "punctual", + "Définir pour les échéances non payées de ce " "bordereau uniquement", + ), + ("all", "Définir pour toutes les prochaines échéances"), + ], + default="punctual", + required=False, + ) # ------------------------------------------------------ # Action Button @@ -30,29 +36,43 @@ class ScopBordereauChangePaymentMode(models.TransientModel): def action_change_payment_mode(self): bordereau_id = self.bordereau_id # Link new liasse fiscale to bordereau - if self.change_type == 'all': - bordereau_id.partner_id.update({ - 'customer_payment_mode_id': self.payment_mode_id.id, - }) - bordereau_id.update({ - 'payment_mode_id': self.payment_mode_id.id, - }) - bordereau_id.invoice_ids.update({ - 'payment_mode_id': self.payment_mode_id.id, - }) + if self.change_type == "all": + bordereau_id.partner_id.update( + { + "customer_payment_mode_id": self.payment_mode_id.id, + } + ) + bordereau_id.update( + { + "payment_mode_id": self.payment_mode_id.id, + } + ) + bordereau_id.invoice_ids.update( + { + "payment_mode_id": self.payment_mode_id.id, + } + ) contrib_cg_journal = self.env.user.company_id.contribution_journal_id - contrib_ur_fede_journal = \ + contrib_ur_fede_journal = ( self.env.user.company_id.contribution_ur_or_fede_journal_id - move_line_ids = self.env['account.move.line'].search([ - ('partner_id', '=', self.bordereau_id.partner_id.id), - ('journal_id', 'in', ( - contrib_cg_journal.id, contrib_ur_fede_journal.id)), - ('full_reconcile_id', '=', False), - ('balance', '!=', 0), - ('account_id.reconcile', '=', True), - ('account_id.internal_type', '=', 'receivable') - ]) - move_line_ids.update({ - 'payment_mode_id': self.payment_mode_id.id, - }) - return {'type': 'ir.actions.act_window_close'} + ) + move_line_ids = self.env["account.move.line"].search( + [ + ("partner_id", "=", self.bordereau_id.partner_id.id), + ( + "journal_id", + "in", + (contrib_cg_journal.id, contrib_ur_fede_journal.id), + ), + ("full_reconcile_id", "=", False), + ("balance", "!=", 0), + ("account_id.reconcile", "=", True), + ("account_id.internal_type", "=", "receivable"), + ] + ) + move_line_ids.update( + { + "payment_mode_id": self.payment_mode_id.id, + } + ) + return {"type": "ir.actions.act_window_close"} diff --git a/wizard/scop_bordereau_payment_mode_wizard.xml b/wizard/scop_bordereau_payment_mode_wizard.xml index 4af8d77fe44f19aefa6aac02dae0c207c42122f6..10f4a820f3712580f9a7051a7e552b62c34bdc4b 100644 --- a/wizard/scop_bordereau_payment_mode_wizard.xml +++ b/wizard/scop_bordereau_payment_mode_wizard.xml @@ -1,25 +1,46 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <data> - <record id="scop_bordereau_change_payment_mode_wizard_form_view" model="ir.ui.view"> + <record + id="scop_bordereau_change_payment_mode_wizard_form_view" + model="ir.ui.view" + > <field name="name">scop.bordereau.change.payment.mode.wizard.form</field> <field name="model">scop.bordereau.change.payment.mode.wizard</field> <field name="arch" type="xml"> <form string="Changement de mode de paiement"> <group> - <field name="payment_mode_id" options="{'no_open': True, 'no_create': True}"/> - <field name="change_type" widget="radio" nolabel="1" class="mt-4"/> + <field + name="payment_mode_id" + options="{'no_open': True, 'no_create': True}" + /> + <field + name="change_type" + widget="radio" + nolabel="1" + class="mt-4" + /> </group> <footer> - <button name="action_change_payment_mode" string="Ok" type="object" default_focus="1" class="oe_highlight"/> - <button class="oe_highlight" string="Annuler" special="cancel"/> + <button + name="action_change_payment_mode" + string="Ok" + type="object" + default_focus="1" + class="oe_highlight" + /> + <button + class="oe_highlight" + string="Annuler" + special="cancel" + /> </footer> </form> </field> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/wizard/scop_bordereau_refund_wizard.py b/wizard/scop_bordereau_refund_wizard.py index 53614d19218f20135ec17c2e5150aeb6b42ed92e..0d6a8af5feb67f611847fb573f7c693343e595f0 100644 --- a/wizard/scop_bordereau_refund_wizard.py +++ b/wizard/scop_bordereau_refund_wizard.py @@ -1,46 +1,53 @@ # Copyright 2021 Le Filament # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models, api -from odoo.exceptions import ValidationError, UserError +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError class ScopBordereauRefundWizard(models.TransientModel): - _name = 'scop.bordereau.refund.wizard' - _description = 'Avoir sur les bordereaux' + _name = "scop.bordereau.refund.wizard" + _description = "Avoir sur les bordereaux" bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau', + comodel_name="scop.bordereau", + string="Bordereau", readonly=True, ) date_refund = fields.Date( string="Date de régularisation", - default=fields.Date.today(), required=1) - cotiz_reminder = fields.Html('Rappel des cotisations', readonly=1) - amount_refund = fields.Float('Montant (par trimestre)', required=1) - comment = fields.Char('Motif de l\'avoir', required=1) + default=fields.Date.today(), + required=1, + ) + cotiz_reminder = fields.Html("Rappel des cotisations", readonly=1) + amount_refund = fields.Float("Montant (par trimestre)", required=1) + comment = fields.Char("Motif de l'avoir", required=1) type_cotiz = fields.Selection( - string='Type de cotisation', + string="Type de cotisation", selection=lambda self: self._selection_type_cotiz(), - required=1) + required=1, + ) quarter_ids = fields.Many2many( - relation='scop_bordereau_refund_wizard_quarter_rel', - comodel_name='scop.bordereau.refund.wizard.quarter', - string='Trimestres') + relation="scop_bordereau_refund_wizard_quarter_rel", + comodel_name="scop.bordereau.refund.wizard.quarter", + string="Trimestres", + ) # ------------------------------------------------------ # Constrains # ------------------------------------------------------ - @api.constrains('date_refund') + @api.constrains("date_refund") def _check_date_refund(self): - last_date = max(self.bordereau_id.invoice_ids.mapped('date_invoice')) - if self.date_refund > fields.Date.today() or \ - self.date_refund < last_date: - raise ValidationError("La date de l'avoir doit être " - "inférieure ou égale à la date du jour et " - "supérieure à la dernière date de " - "facturation liée au bordereau.") + last_date = max(self.bordereau_id.invoice_ids.mapped("date_invoice")) + if self.date_refund > fields.Date.today() or self.date_refund < last_date: + raise ValidationError( + _( + "La date de l'avoir doit être " + "inférieure ou égale à la date du jour et " + "supérieure à la dernière date de " + "facturation liée au bordereau." + ) + ) # ------------------------------------------------------ # Override ORM @@ -48,51 +55,55 @@ class ScopBordereauRefundWizard(models.TransientModel): @api.model def default_get(self, fields): res = super(ScopBordereauRefundWizard, self).default_get(fields) - bordereau_id = self.env['scop.bordereau'].browse( - self.env.context.get('active_id') + bordereau_id = self.env["scop.bordereau"].browse( + self.env.context.get("active_id") + ) + res.update( + { + "bordereau_id": bordereau_id.id, + "cotiz_reminder": bordereau_id.details, + } ) - res.update({ - 'bordereau_id': bordereau_id.id, - 'cotiz_reminder': bordereau_id.details, - }) return res @api.model def _selection_type_cotiz(self): - bordereau_id = self.env['scop.bordereau'].browse( - self.env.context.get('active_id') + bordereau_id = self.env["scop.bordereau"].browse( + self.env.context.get("active_id") ) contribs = bordereau_id.invoice_ids.read_group( - [('id', 'in', bordereau_id.invoice_ids.ids)], - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + [("id", "in", bordereau_id.invoice_ids.ids)], + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) - ur_hdf = self.env.ref('cgscop_partner.riga_14232').id + ur_hdf = self.env.ref("cgscop_partner.riga_14232").id if bordereau_id.partner_id.ur_id.id == ur_hdf: product_ur = self.env.user.company_id.contribution_hdf_id else: # ur = ur_med product_ur = self.env.user.company_id.contribution_med_id cotiz_type = { - self.env.ref('cgscop_partner.riga_14397').id: - self.env.user.company_id.contribution_cg_id, - self.env.ref('cgscop_partner.riga_14398').id: - self.env.user.company_id.contribution_fede_com_id, - self.env.ref('cgscop_partner.cotiz_fede_cae').id: - self.env.user.company_id.contribution_fede_cae_id, - self.env.ref('cgscop_partner.riga_14399').id: - product_ur, + self.env.ref( + "cgscop_partner.riga_14397" + ).id: self.env.user.company_id.contribution_cg_id, + self.env.ref( + "cgscop_partner.riga_14398" + ).id: self.env.user.company_id.contribution_fede_com_id, + self.env.ref( + "cgscop_partner.cotiz_fede_cae" + ).id: self.env.user.company_id.contribution_fede_cae_id, + self.env.ref("cgscop_partner.riga_14399").id: product_ur, } type_cotiz_select_i = list() type_cotiz_select_list = list() for contrib in contribs: - type_cotiz = contrib.get('type_contribution_id')[0] + type_cotiz = contrib.get("type_contribution_id")[0] if type_cotiz not in type_cotiz_select_i: type_cotiz_select_i.append(type_cotiz) - type_cotiz_select_list.append( - (type_cotiz, cotiz_type[type_cotiz].name)) + type_cotiz_select_list.append((type_cotiz, cotiz_type[type_cotiz].name)) return type_cotiz_select_list # ------------------------------------------------------ @@ -103,31 +114,33 @@ class ScopBordereauRefundWizard(models.TransientModel): Create refund """ if len(self.quarter_ids) == 0: - raise UserError('Vous devez sélectionner au moins un trimestre.') + raise UserError(_("Vous devez sélectionner au moins un trimestre.")) if self.amount_refund <= 0: - raise UserError('Le montant de l\'avoir doit être supérieur à 0.') + raise UserError(_("Le montant de l'avoir doit être supérieur à 0.")) if not self.type_cotiz: - raise UserError('Vous devez sélectionner un type de cotisation.') + raise UserError(_("Vous devez sélectionner un type de cotisation.")) bordereau_id = self.bordereau_id partner_id = bordereau_id.partner_id - ur_hdf = self.env.ref('cgscop_partner.riga_14232').id + ur_hdf = self.env.ref("cgscop_partner.riga_14232").id # CREATE VERSION - bordereau_id.read(['amount_total_cotiz']) + bordereau_id.read(["amount_total_cotiz"]) ongoing_version = bordereau_id.bordereau_version_ids.filtered( - lambda v: v.version == bordereau_id.version and v.state == 'new' + lambda v: v.version == bordereau_id.version and v.state == "new" ) if not ongoing_version: - self.env['scop.bordereau.version'].create({ - 'bordereau_id': bordereau_id.id, - 'date': self.date_refund, - 'comment': self.comment, - 'version': bordereau_id.version, - 'liasse_fiscale_id_old': bordereau_id.liasse_fiscale_id.id, - 'type_assiette': bordereau_id.type_assiette, - 'montant_assiette': bordereau_id.montant_assiette, - 'amount_total_cotiz': bordereau_id.amount_total_cotiz, - }) + self.env["scop.bordereau.version"].create( + { + "bordereau_id": bordereau_id.id, + "date": self.date_refund, + "comment": self.comment, + "version": bordereau_id.version, + "liasse_fiscale_id_old": bordereau_id.liasse_fiscale_id.id, + "type_assiette": bordereau_id.type_assiette, + "montant_assiette": bordereau_id.montant_assiette, + "amount_total_cotiz": bordereau_id.amount_total_cotiz, + } + ) # CREATE REFUND if partner_id.ur_id.id == ur_hdf: @@ -138,63 +151,70 @@ class ScopBordereauRefundWizard(models.TransientModel): account_ur = self.env.user.company_id.receivable_account_ur_med_id cotiz_type = { - self.env.ref('cgscop_partner.riga_14397').id: - [self.env.user.company_id.contribution_cg_id, - self.env.user.company_id.contribution_journal_id, - partner_id.property_account_receivable_id], - self.env.ref('cgscop_partner.riga_14398').id: - [self.env.user.company_id.contribution_fede_com_id, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - self.env.user.company_id.receivable_account_fede_com_id], - self.env.ref('cgscop_partner.cotiz_fede_cae').id: - [self.env.user.company_id.contribution_fede_cae_id, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - self.env.user.company_id.receivable_account_fede_cae_id], - self.env.ref('cgscop_partner.riga_14399').id: - [product_ur, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - account_ur], + self.env.ref("cgscop_partner.riga_14397").id: [ + self.env.user.company_id.contribution_cg_id, + self.env.user.company_id.contribution_journal_id, + partner_id.property_account_receivable_id, + ], + self.env.ref("cgscop_partner.riga_14398").id: [ + self.env.user.company_id.contribution_fede_com_id, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + self.env.user.company_id.receivable_account_fede_com_id, + ], + self.env.ref("cgscop_partner.cotiz_fede_cae").id: [ + self.env.user.company_id.contribution_fede_cae_id, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + self.env.user.company_id.receivable_account_fede_cae_id, + ], + self.env.ref("cgscop_partner.riga_14399").id: [ + product_ur, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + account_ur, + ], } product = cotiz_type.get(int(self.type_cotiz))[0] for quarter_id in self.quarter_ids: - refund = self.env['account.invoice'].create({ - 'partner_id': partner_id.id, - 'journal_id': cotiz_type.get(int(self.type_cotiz))[1].id, - 'account_id': cotiz_type.get(int(self.type_cotiz))[2].id, - 'type': 'out_refund', - 'date_invoice': self.date_refund, - 'date': self.date_refund, - 'state': 'draft', - 'number': False, - 'origin': bordereau_id.name, - 'name': self.comment, - 'bordereau_id': bordereau_id.id, - 'is_contribution': True, - 'year': bordereau_id.year, - 'cotiz_quarter': quarter_id.quarter, - 'liasse_fiscale_id': bordereau_id.liasse_fiscale_id.id, - 'type_contribution_id': self.type_cotiz, - 'payment_mode_id': bordereau_id.payment_mode_id.id, - 'date_due': self.date_refund, - }) - self.env['account.invoice.line'].create({ - 'name': self.comment, - 'invoice_id': refund.id, - 'product_id': product.id, - 'account_id': product.property_account_income_id.id, - 'price_unit': self.amount_refund - }) + refund = self.env["account.invoice"].create( + { + "partner_id": partner_id.id, + "journal_id": cotiz_type.get(int(self.type_cotiz))[1].id, + "account_id": cotiz_type.get(int(self.type_cotiz))[2].id, + "type": "out_refund", + "date_invoice": self.date_refund, + "date": self.date_refund, + "state": "draft", + "number": False, + "origin": bordereau_id.name, + "name": self.comment, + "bordereau_id": bordereau_id.id, + "is_contribution": True, + "year": bordereau_id.year, + "cotiz_quarter": quarter_id.quarter, + "liasse_fiscale_id": bordereau_id.liasse_fiscale_id.id, + "type_contribution_id": self.type_cotiz, + "payment_mode_id": bordereau_id.payment_mode_id.id, + "date_due": self.date_refund, + } + ) + self.env["account.invoice.line"].create( + { + "name": self.comment, + "invoice_id": refund.id, + "product_id": product.id, + "account_id": product.property_account_income_id.id, + "price_unit": self.amount_refund, + } + ) class ScopBordereauRefundWizardQuarer(models.Model): - _name = 'scop.bordereau.refund.wizard.quarter' - _description = 'Trimestres pour échéance de cotisation' + _name = "scop.bordereau.refund.wizard.quarter" + _description = "Trimestres pour échéance de cotisation" - name = fields.Char('Nom', compute='_compute_name') - quarter = fields.Integer('Trismestre', required=1) + name = fields.Char("Nom", compute="_compute_name") + quarter = fields.Integer("Trimestre", required=1) - @api.multi def _compute_name(self): for r in self: r.name = str(r.quarter) diff --git a/wizard/scop_bordereau_refund_wizard.xml b/wizard/scop_bordereau_refund_wizard.xml index e42f5c0268bb3f78a2a2faeb20aead211ea6b5c8..e20305b8b440864e2cd43e8cbad4677f36274816 100644 --- a/wizard/scop_bordereau_refund_wizard.xml +++ b/wizard/scop_bordereau_refund_wizard.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> @@ -11,32 +11,39 @@ <form string="Générer un avoir"> <sheet> <group> - <field name="cotiz_reminder"/> - <hr/> - <field name="type_cotiz"/> - <field name="date_refund"/> - <separator/> - <field name="amount_refund"/> - <field name="quarter_ids" widget="many2many_checkboxes"/> - <field name="comment"/> + <field name="cotiz_reminder" /> + <hr /> + <field name="type_cotiz" /> + <field name="date_refund" /> + <separator /> + <field name="amount_refund" /> + <field name="quarter_ids" widget="many2many_checkboxes" /> + <field name="comment" /> </group> </sheet> <footer> - <button name="create_refund" type="object" string="Créer l'avoir" class="oe_highlight"/> - <button string="Annuler" special="cancel" class="oe_link"/> + <button + name="create_refund" + type="object" + string="Créer l'avoir" + class="oe_highlight" + /> + <button string="Annuler" special="cancel" class="oe_link" /> </footer> </form> </field> </record> - <record id="scop_bordereau_refund_wizard_act_window" model="ir.actions.act_window"> + <record + id="scop_bordereau_refund_wizard_act_window" + model="ir.actions.act_window" + > <field name="name">Avoir sur le bordereau</field> <field name="type">ir.actions.act_window</field> <field name="res_model">scop.bordereau.refund.wizard</field> - <field name="view_type">form</field> <field name="view_mode">form</field> <field name="target">new</field> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/wizard/scop_bordereau_update_confirm.py b/wizard/scop_bordereau_update_confirm.py index d14e35b55aae3103f33a53f7e3c5e89f5e607790..2a0ed5e3604c79f0b4b027d2eadb8061e376a8d9 100644 --- a/wizard/scop_bordereau_update_confirm.py +++ b/wizard/scop_bordereau_update_confirm.py @@ -1,7 +1,7 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) -from odoo import models, api, _ +from odoo import _, models from odoo.exceptions import UserError @@ -13,14 +13,17 @@ class ScopBordereauUpdate(models.TransientModel): _name = "scop.bordereau.update" _description = "Mettre à jour les bordereaux sélectionnés" - @api.multi def bordereau_update(self): context = dict(self._context or {}) - active_ids = context.get('active_ids', []) or [] + active_ids = context.get("active_ids", []) or [] - for record in self.env['scop.bordereau'].browse(active_ids): - if record.state != 'new': - raise UserError(_("Impossible de mettre à jour un bordereau " - "qui n'est pas à l'état de brouillon")) + for record in self.env["scop.bordereau"].browse(active_ids): + if record.state != "new": + raise UserError( + _( + "Impossible de mettre à jour un bordereau " + "qui n'est pas à l'état de brouillon" + ) + ) record.create_cotiz_and_lines() - return {'type': 'ir.actions.act_window_close'} + return {"type": "ir.actions.act_window_close"} diff --git a/wizard/scop_bordereau_update_confirm_view.xml b/wizard/scop_bordereau_update_confirm_view.xml index a68680b7503aba8957286f36b55084ca60778a52..0a5396534b62b780628ad2e6b7028e1152293ec9 100644 --- a/wizard/scop_bordereau_update_confirm_view.xml +++ b/wizard/scop_bordereau_update_confirm_view.xml @@ -1,10 +1,8 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> - <record id="account_invoice_update_view" model="ir.ui.view"> <field name="name">scop.bordereau.update.form</field> <field name="model">scop.bordereau.update</field> @@ -14,18 +12,30 @@ Cette action est susceptible de modifier les montants des cotisations ! </p> <footer> - <button string="Valider" name="bordereau_update" type="object" default_focus="1" class="btn-primary"/> - <button string="Annuler" class="btn-secondary" special="cancel"/> + <button + string="Valider" + name="bordereau_update" + type="object" + default_focus="1" + class="btn-primary" + /> + <button + string="Annuler" + class="btn-secondary" + special="cancel" + /> </footer> </form> </field> </record> - <act_window id="action_scop_bordereau_update" - multi="True" - name="Mettre le(s) cotisation(s) à jour" - res_model="scop.bordereau.update" src_model="scop.bordereau" - view_mode="form" target="new" view_type="form" /> + <record id="action_scop_bordereau_update" model="ir.actions.act_window"> + <field name="name">Mettre le(s) cotisation(s) à jour</field> + <field name="res_model">scop.bordereau.update</field> + <field name="binding_model_id" ref="model_scop_bordereau" /> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> </data> </odoo> diff --git a/wizard/scop_bordereau_update_liasse_wizard.py b/wizard/scop_bordereau_update_liasse_wizard.py index bd0ed6a8e3b00af425a11a042bfc0a1100ee1759..4f753f1ca813971da2e751f08a3365823d7ee7fa 100644 --- a/wizard/scop_bordereau_update_liasse_wizard.py +++ b/wizard/scop_bordereau_update_liasse_wizard.py @@ -1,108 +1,103 @@ # Copyright 2021 Le Filament # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models, api +from odoo import _, api, fields, models from odoo.exceptions import UserError class ScopBordereauChangeLiasse(models.TransientModel): - _name = 'scop.bordereau.change.liasse.wizard' - _description = 'Changement de liasse sur le bordereau' + _name = "scop.bordereau.change.liasse.wizard" + _description = "Changement de liasse sur le bordereau" bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau', + comodel_name="scop.bordereau", + string="Bordereau", readonly=True, ) - partner_id = fields.Many2one( - related='bordereau_id.partner_id' - ) - company_currency_id = fields.Many2one( - related='bordereau_id.company_currency_id') + partner_id = fields.Many2one(related="bordereau_id.partner_id") + company_currency_id = fields.Many2one(related="bordereau_id.company_currency_id") # Ancienne liasse - liasse_fiscale_id = fields.Many2one( - related='bordereau_id.liasse_fiscale_id' - ) + liasse_fiscale_id = fields.Many2one(related="bordereau_id.liasse_fiscale_id") amount_total_cotiz = fields.Monetary( - related='bordereau_id.amount_total_cotiz', - currency_field='company_currency_id' + related="bordereau_id.amount_total_cotiz", + currency_field="company_currency_id", ) amount_cg = fields.Float( - 'Cotisation CG Scop actuelle', compute='_compute_amount_cotiz') + "Cotisation CG Scop actuelle", compute="_compute_amount_cotiz" + ) amount_ur_med = fields.Float( - 'Cotisation UR Med actuelle', compute='_compute_amount_cotiz') + "Cotisation UR Med actuelle", compute="_compute_amount_cotiz" + ) amount_ur_hdf = fields.Float( - 'Cotisation UR HDF actuelle', compute='_compute_amount_cotiz') + "Cotisation UR HDF actuelle", compute="_compute_amount_cotiz" + ) amount_fede_com = fields.Float( - 'Cotisation Fede Com actuelle', compute='_compute_amount_cotiz') + "Cotisation Fede Com actuelle", compute="_compute_amount_cotiz" + ) amount_fede_cae = fields.Float( - 'Cotisation Fede CAE actuelle', compute='_compute_amount_cotiz') + "Cotisation Fede CAE actuelle", compute="_compute_amount_cotiz" + ) type_assiette = fields.Selection( - string='Type d\'assiette', - related='bordereau_id.type_assiette',) + string="Type d'assiette", + related="bordereau_id.type_assiette", + ) montant_assiette = fields.Integer( - string='Montant de l\'assiette', - related='bordereau_id.montant_assiette') - ca = fields.Float( - related='bordereau_id.ca') - va = fields.Float( - related='bordereau_id.va') - net_results = fields.Float( - related='bordereau_id.net_results') - wage_cg = fields.Float( - related='bordereau_id.wage_cg') + string="Montant de l'assiette", related="bordereau_id.montant_assiette" + ) + ca = fields.Float(related="bordereau_id.ca") + va = fields.Float(related="bordereau_id.va") + net_results = fields.Float(related="bordereau_id.net_results") + wage_cg = fields.Float(related="bordereau_id.wage_cg") # Nouvelle liasse liasse_fiscale_new_id = fields.Many2one( - comodel_name='scop.liasse.fiscale', - string='Nouvelle liasse Fiscale', + comodel_name="scop.liasse.fiscale", + string="Nouvelle liasse Fiscale", ) amount_total_cotiz_new = fields.Monetary( - string='Nouveau montant total de(s) cotisation(s)', - currency_field='company_currency_id', - readonly=1) + string="Nouveau montant total de(s) cotisation(s)", + currency_field="company_currency_id", + readonly=1, + ) type_id_new = fields.Selection( - 'Type de liasse', related='liasse_fiscale_new_id.type_id') + string="Type de liasse", related="liasse_fiscale_new_id.type_id" + ) source_new = fields.Selection( - 'Source de la liasse', related='liasse_fiscale_new_id.source') + string="Source de la liasse", related="liasse_fiscale_new_id.source" + ) amount_cg_new = fields.Float( - 'Cotisation CG Scop', - related='liasse_fiscale_new_id.contribution_cg') + "Cotisation CG Scop", related="liasse_fiscale_new_id.contribution_cg" + ) amount_ur_med_new = fields.Float( - 'Cotisation UR Méditerranée', - related='liasse_fiscale_new_id.contribution_med') + "Cotisation UR Méditerranée", + related="liasse_fiscale_new_id.contribution_med", + ) amount_ur_hdf_new = fields.Float( - 'Cotisation UR HDF', - related='liasse_fiscale_new_id.contribution_hdf') + "Cotisation UR HDF", related="liasse_fiscale_new_id.contribution_hdf" + ) amount_fede_com_new = fields.Float( - 'Cotisation Fédé Communication', - related='liasse_fiscale_new_id.contribution_com') + "Cotisation Fédé Communication", + related="liasse_fiscale_new_id.contribution_com", + ) amount_fede_cae_new = fields.Float( - 'Cotisation Fédé CAE', - related='liasse_fiscale_new_id.contribution_cae') + "Cotisation Fédé CAE", related="liasse_fiscale_new_id.contribution_cae" + ) type_assiette_new = fields.Selection( - related='liasse_fiscale_new_id.contribution_base_type') + related="liasse_fiscale_new_id.contribution_base_type" + ) montant_assiette_new = fields.Integer( - related='liasse_fiscale_new_id.contribution_base_amount') - # ca_new = fields.Float( - # related='liasse_fiscale_new_id.av_cg') - # va_new = fields.Float( - # string='VA', compute='_compute_liasse_new_values') - # net_results_new = fields.Float( - # string='Résultat net', compute='_compute_liasse_new_values') - # wage_cg_new = fields.Float( - # string='Montant masse salariale', compute='_compute_liasse_new_values') + related="liasse_fiscale_new_id.contribution_base_amount" + ) # ------------------------------------------------------ # Compute # ------------------------------------------------------ def _compute_amount_cotiz(self): - type_cotisation_cg = self.env.ref('cgscop_partner.riga_14397').id - type_cotisation_fede_com = self.env.ref('cgscop_partner.riga_14398').id - type_cotisation_fede_cae = self.env.ref( - 'cgscop_partner.cotiz_fede_cae').id - type_cotisation_ur = self.env.ref('cgscop_partner.riga_14399').id + type_cotisation_cg = self.env.ref("cgscop_partner.riga_14397").id + type_cotisation_fede_com = self.env.ref("cgscop_partner.riga_14398").id + type_cotisation_fede_cae = self.env.ref("cgscop_partner.cotiz_fede_cae").id + type_cotisation_ur = self.env.ref("cgscop_partner.riga_14399").id for r in self: partner = r.bordereau_id.partner_id cotiz = r.bordereau_id.invoice_ids @@ -110,42 +105,45 @@ class ScopBordereauChangeLiasse(models.TransientModel): cotiz_cg = cotiz.filtered( lambda i: i.type_contribution_id.id == type_cotisation_cg ) - r.amount_cg = sum(cotiz_cg.mapped('amount_total')) + r.amount_cg = sum(cotiz_cg.mapped("amount_total")) # Fede Com cotiz_fede_com = cotiz.filtered( lambda i: i.type_contribution_id.id == type_cotisation_fede_com ) - r.amount_fede_com = sum(cotiz_fede_com.mapped('amount_total')) + r.amount_fede_com = sum(cotiz_fede_com.mapped("amount_total")) # Fede CAE cotiz_fede_cae = cotiz.filtered( lambda i: i.type_contribution_id.id == type_cotisation_fede_cae ) - r.amount_fede_cae = sum(cotiz_fede_cae.mapped('amount_total')) + r.amount_fede_cae = sum(cotiz_fede_cae.mapped("amount_total")) # UR HDF - ur_hdf = self.env.ref('cgscop_partner.riga_14232').id + ur_hdf = self.env.ref("cgscop_partner.riga_14232").id if partner.ur_id.id == ur_hdf: cotiz_ur_hdf = cotiz.filtered( lambda i: i.type_contribution_id.id == type_cotisation_ur ) - r.amount_ur_hdf = sum(cotiz_ur_hdf.mapped('amount_total')) + r.amount_ur_hdf = sum(cotiz_ur_hdf.mapped("amount_total")) # UR Med - ur_med = self.env.ref('cgscop_partner.riga_14243').id + ur_med = self.env.ref("cgscop_partner.riga_14243").id if partner.ur_id.id == ur_med: cotiz_ur_med = cotiz.filtered( lambda i: i.type_contribution_id.id == type_cotisation_ur ) - r.amount_ur_med = sum(cotiz_ur_med.mapped('amount_total')) + r.amount_ur_med = sum(cotiz_ur_med.mapped("amount_total")) # ------------------------------------------------------ # Onchange # ------------------------------------------------------ - @api.onchange('liasse_fiscale_new_id') + @api.onchange("liasse_fiscale_new_id") def _compute_liasse_new_values(self): for r in self: if r.liasse_fiscale_new_id: - r.amount_total_cotiz_new = \ - r.amount_cg_new + r.amount_ur_hdf_new + \ - r.amount_ur_med_new + r.amount_fede_com + r.amount_total_cotiz_new = ( + r.amount_cg_new + + r.amount_ur_hdf_new + + r.amount_ur_med_new + + r.amount_fede_com + ) # ------------------------------------------------------ # Action Button @@ -153,10 +151,12 @@ class ScopBordereauChangeLiasse(models.TransientModel): def update_liasse_fiscale(self): bordereau_id = self.bordereau_id if not self.liasse_fiscale_new_id: - raise UserError('Merci de choisir une nouvelle liasse fiscale.') + raise UserError(_("Merci de choisir une nouvelle liasse fiscale.")) # Link new liasse fiscale to bordereau - bordereau_id.update({ - 'liasse_fiscale_id': self.liasse_fiscale_new_id, - }) + bordereau_id.update( + { + "liasse_fiscale_id": self.liasse_fiscale_new_id, + } + ) bordereau_id.create_cotiz_and_lines() - return {'type': 'ir.actions.act_window_close'} + return {"type": "ir.actions.act_window_close"} diff --git a/wizard/scop_bordereau_update_liasse_wizard.xml b/wizard/scop_bordereau_update_liasse_wizard.xml index 610d83f7e9506e2d10f870c89c5f857890d92a4d..125e66c599121ff38c782db6b517c09a24d5a9a7 100644 --- a/wizard/scop_bordereau_update_liasse_wizard.xml +++ b/wizard/scop_bordereau_update_liasse_wizard.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> @@ -13,65 +13,112 @@ <div class="row"> <div class="col-6"> <group string="Données initiales" class="text-muted"> - <field name="liasse_fiscale_id" options='{"no_open": True}'/> - <hr/> - <field name="amount_total_cotiz"/> - <field name="amount_cg"/> - <field name="amount_ur_med" attrs="{'invisible':[('amount_ur_med','=',0)]}"/> - <field name="amount_ur_hdf" attrs="{'invisible':[('amount_ur_hdf','=',0)]}"/> - <field name="amount_fede_com" attrs="{'invisible':[('amount_fede_com','=',0)]}"/> - <field name="amount_fede_cae" attrs="{'invisible':[('amount_fede_cae','=',0)]}"/> - <hr/> - <field name="type_assiette"/> - <field name="montant_assiette"/> - <hr/> - <field name="ca"/> - <field name="va"/> - <field name="net_results"/> - <field name="wage_cg"/> + <field + name="liasse_fiscale_id" + options='{"no_open": True}' + /> + <hr /> + <field name="amount_total_cotiz" /> + <field name="amount_cg" /> + <field + name="amount_ur_med" + attrs="{'invisible':[('amount_ur_med','=',0)]}" + /> + <field + name="amount_ur_hdf" + attrs="{'invisible':[('amount_ur_hdf','=',0)]}" + /> + <field + name="amount_fede_com" + attrs="{'invisible':[('amount_fede_com','=',0)]}" + /> + <field + name="amount_fede_cae" + attrs="{'invisible':[('amount_fede_cae','=',0)]}" + /> + <hr /> + <field name="type_assiette" /> + <field name="montant_assiette" /> + <hr /> + <field name="ca" /> + <field name="va" /> + <field name="net_results" /> + <field name="wage_cg" /> </group> </div> <div class="col-6"> <group> - <field name="partner_id" invisible="1"/> - <field name="liasse_fiscale_new_id" options='{"no_open": True, "no_create":True}' - domain="[('partner_id', '=', partner_id), + <field name="partner_id" invisible="1" /> + <field + name="liasse_fiscale_new_id" + options='{"no_open": True, "no_create":True}' + domain="[('partner_id', '=', partner_id), ('is_qualified', '=', True), - ('id', '!=', liasse_fiscale_id)]"/> - <field name="type_id_new" attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}"/> - <field name="source_new" attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}"/> + ('id', '!=', liasse_fiscale_id)]" + /> + <field + name="type_id_new" + attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}" + /> + <field + name="source_new" + attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}" + /> </group> - <group string="Nouveaux calculs (Sans arrondi)" attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}"> - <field name="amount_total_cotiz_new"/> - <field name="amount_cg_new"/> - <field name="amount_ur_med_new" attrs="{'invisible':[('amount_ur_med_new','=',0)]}"/> - <field name="amount_ur_hdf_new" attrs="{'invisible':[('amount_ur_hdf_new','=',0)]}"/> - <field name="amount_fede_com_new" attrs="{'invisible':[('amount_fede_com_new','=',0)]}"/> - <field name="amount_fede_cae_new" attrs="{'invisible':[('amount_fede_cae_new','=',0)]}"/> - <hr/> - <field name="type_assiette_new"/> - <field name="montant_assiette_new"/> - <hr/> + <group + string="Nouveaux calculs (Sans arrondi)" + attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}" + > + <field name="amount_total_cotiz_new" /> + <field name="amount_cg_new" /> + <field + name="amount_ur_med_new" + attrs="{'invisible':[('amount_ur_med_new','=',0)]}" + /> + <field + name="amount_ur_hdf_new" + attrs="{'invisible':[('amount_ur_hdf_new','=',0)]}" + /> + <field + name="amount_fede_com_new" + attrs="{'invisible':[('amount_fede_com_new','=',0)]}" + /> + <field + name="amount_fede_cae_new" + attrs="{'invisible':[('amount_fede_cae_new','=',0)]}" + /> + <hr /> + <field name="type_assiette_new" /> + <field name="montant_assiette_new" /> + <hr /> </group> </div> </div> </sheet> <footer> - <button name="update_liasse_fiscale" type="object" string="Modifier la liasse" class="oe_highlight" confirm="Confirmer le changement de liasse"/> - <button string="Annuler" special="cancel" class="oe_link"/> + <button + name="update_liasse_fiscale" + type="object" + string="Modifier la liasse" + class="oe_highlight" + confirm="Confirmer le changement de liasse" + /> + <button string="Annuler" special="cancel" class="oe_link" /> </footer> </form> </field> </record> - <record id="scop_bordereau_change_liasse_wizard_act_window" model="ir.actions.act_window"> + <record + id="scop_bordereau_change_liasse_wizard_act_window" + model="ir.actions.act_window" + > <field name="name">Changement liasse bordereau</field> <field name="type">ir.actions.act_window</field> <field name="res_model">scop.bordereau.change.liasse.wizard</field> - <field name="view_type">form</field> <field name="view_mode">form</field> <field name="target">new</field> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/wizard/scop_bordereau_validate_confirm.py b/wizard/scop_bordereau_validate_confirm.py index 023cc3b9a8c31832e44bf5df660c581dfdc2f48b..8ca1fcb498d9004e5af849a368c91a9032fe9250 100644 --- a/wizard/scop_bordereau_validate_confirm.py +++ b/wizard/scop_bordereau_validate_confirm.py @@ -1,7 +1,7 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) -from odoo import models, api, fields, _ +from odoo import _, api, fields, models from odoo.exceptions import UserError @@ -9,47 +9,54 @@ class ScopBordereauValidate(models.TransientModel): """ This wizard will validate all the selected bordereaux """ + _name = "scop.bordereau.validate" _description = "Valider les bordereaux sélectionnés" @api.model def default_get(self, fields): res = super(ScopBordereauValidate, self).default_get(fields) - template_id = self.env.ref( - 'cgscop_cotisation_cg.email_template_cotisation_cg') - res.update({ - 'subject': template_id.subject, - 'body_html': template_id.body_html, - }) + template_id = self.env.ref("cgscop_cotisation_cg.email_template_cotisation_cg") + res.update( + { + "subject": template_id.subject, + "body_html": template_id.body_html, + } + ) return res - subject = fields.Char('Objet:', translate=True, sanitize=False) - body_html = fields.Html('Corps du mail:', translate=True, sanitize=False) + subject = fields.Char("Objet:", translate=True) + body_html = fields.Html("Corps du mail:", translate=True, sanitize=False) - @api.multi def bordereau_validate(self): context = dict(self._context or {}) - active_ids = context.get('active_ids', []) or [] + active_ids = context.get("active_ids", []) or [] - bordereau_ids = self.env['scop.bordereau'].browse(active_ids) - not_new_bordereau = bordereau_ids.filtered( - lambda b: b.state != 'new') + bordereau_ids = self.env["scop.bordereau"].browse(active_ids) + not_new_bordereau = bordereau_ids.filtered(lambda b: b.state != "new") if not_new_bordereau: - raise UserError(_("Impossible de valider un bordereau qui " - "n'est pas à l'état de brouillon")) + raise UserError( + _( + "Impossible de valider un bordereau qui " + "n'est pas à l'état de brouillon" + ) + ) else: template_id = self.env.ref( - 'cgscop_cotisation_cg.email_template_cotisation_cg') - mail_compose_message_id = self.env['mail.compose.message'].create({ - 'subject': self.subject, - 'body': self.body_html, - 'model': 'scop.bordereau', - 'email_from': template_id.email_from, - 'reply_to': template_id.reply_to, - 'auto_delete': False, - 'composition_mode': 'mass_mail', - }) + "cgscop_cotisation_cg.email_template_cotisation_cg" + ) + mail_compose_message_id = self.env["mail.compose.message"].create( + { + "subject": self.subject, + "body": self.body_html, + "model": "scop.bordereau", + "email_from": template_id.email_from, + "reply_to": template_id.reply_to, + "auto_delete": False, + "composition_mode": "mass_mail", + } + ) bordereau_ids.validate_bordereau_multi(mail_compose_message_id.id) - return {'type': 'ir.actions.act_window_close'} + return {"type": "ir.actions.act_window_close"} diff --git a/wizard/scop_bordereau_validate_confirm_view.xml b/wizard/scop_bordereau_validate_confirm_view.xml index 04e7a80aa06ca2517479db318ab6aa84a8bee56f..deec2855f3eb81a1c023df6507d6ac5db65825c5 100644 --- a/wizard/scop_bordereau_validate_confirm_view.xml +++ b/wizard/scop_bordereau_validate_confirm_view.xml @@ -1,7 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> @@ -10,25 +9,37 @@ <field name="model">scop.bordereau.validate</field> <field name="arch" type="xml"> <form string="Valider les bordereaux"> - <field name="subject"/> - <field name="body_html"/> - <hr/> + <field name="subject" /> + <field name="body_html" /> + <hr /> <p class="oe_grey"> Une fois les bordereaux validés, vous ne pourrez plus les remettre en brouillon ! </p> <footer> - <button string="Valider" name="bordereau_validate" type="object" default_focus="1" class="btn-primary"/> - <button string="Annuler" class="btn-secondary" special="cancel"/> + <button + string="Valider" + name="bordereau_validate" + type="object" + default_focus="1" + class="btn-primary" + /> + <button + string="Annuler" + class="btn-secondary" + special="cancel" + /> </footer> </form> </field> </record> - <act_window id="action_scop_bordereau_validate" - multi="True" - name="Valider le(s) bordereau(x)" - res_model="scop.bordereau.validate" src_model="scop.bordereau" - view_mode="form" target="new" view_type="form" /> + <record id="action_scop_bordereau_validate" model="ir.actions.act_window"> + <field name="name">Valider le(s) bordereau(x)</field> + <field name="res_model">scop.bordereau.validate</field> + <field name="binding_model_id" ref="model_scop_bordereau" /> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> </data> </odoo> diff --git a/wizard/scop_cotisation_cg_regul.py b/wizard/scop_cotisation_cg_regul.py index 5f0d6d7a1dc2e469d852148e0399481887e93daa..5b6f5644424d99176eb5564fd852d676837a16d1 100644 --- a/wizard/scop_cotisation_cg_regul.py +++ b/wizard/scop_cotisation_cg_regul.py @@ -1,85 +1,89 @@ # Copyright 2020 Le Filament # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models, api +from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError class ScopCotisationRegul(models.TransientModel): - _name = 'scop.cotisation.regul.wizard' - _description = 'Regularisation cotisation CG' + _name = "scop.cotisation.regul.wizard" + _description = "Regularisation cotisation CG" name = fields.Char() date_regul = fields.Date( - string="Date de régularisation", - default=fields.Date.today()) + string="Date de régularisation", default=fields.Date.today() + ) bordereau_id = fields.Many2one( - comodel_name='scop.bordereau', - string='Bordereau', + comodel_name="scop.bordereau", + string="Bordereau", readonly=True, ) partner_id = fields.Many2one( - comodel_name='res.partner', - string='Adhérent', + comodel_name="res.partner", + string="Adhérent", readonly=True, ) # Old liasse liasse_fiscale_id = fields.Many2one( - comodel_name='scop.liasse.fiscale', - string='Liasse Fiscale de référence', + comodel_name="scop.liasse.fiscale", + string="Liasse Fiscale de référence", ) - year = fields.Integer('Année de la liasse') + year = fields.Integer("Année de la liasse") type_assiette_retenu = fields.Selection( - string='Type assiette', - selection=[('ca', 'CA'), - ('va', 'VA'), ], + string="Type assiette", + selection=[ + ("ca", "CA"), + ("va", "VA"), + ], ) montant_assiette = fields.Float( - string='Montant assiette de cotisation',) - amount_total_cotiz = fields.Float( - string='Montant total de(s) cotisation(s)') - detail = fields.Text('Détail cotisation') - comment = fields.Char('Motif de régularisation') + string="Montant assiette de cotisation", + ) + amount_total_cotiz = fields.Float(string="Montant total de(s) cotisation(s)") + detail = fields.Text("Détail cotisation") + comment = fields.Char("Motif de régularisation") # New liasse liasse_fiscale_new_id = fields.Many2one( - comodel_name='scop.liasse.fiscale', - string='Liasse Fiscale', + comodel_name="scop.liasse.fiscale", + string="Liasse Fiscale", ) type_id_new = fields.Selection( - string='Type de liasse', related='liasse_fiscale_new_id.type_id') + string="Type de liasse", related="liasse_fiscale_new_id.type_id" + ) source_new = fields.Selection( - string='Source de la liasse', related='liasse_fiscale_new_id.source') + string="Source de la liasse", related="liasse_fiscale_new_id.source" + ) type_assiette_new = fields.Selection( - related='liasse_fiscale_new_id.contribution_base_type') + related="liasse_fiscale_new_id.contribution_base_type" + ) montant_assiette_new = fields.Integer( - related='liasse_fiscale_new_id.contribution_base_amount') - amount_cg = fields.Float( - related='liasse_fiscale_new_id.contribution_cg') - amount_ur_med = fields.Float( - related='liasse_fiscale_new_id.contribution_med') - amount_ur_hdf = fields.Float( - related='liasse_fiscale_new_id.contribution_hdf') - amount_fede_com = fields.Float( - related='liasse_fiscale_new_id.contribution_com') - amount_fede_cae = fields.Float( - related='liasse_fiscale_new_id.contribution_cae') - - is_payment = fields.Boolean('Paiements liés') + related="liasse_fiscale_new_id.contribution_base_amount" + ) + amount_cg = fields.Float(related="liasse_fiscale_new_id.contribution_cg") + amount_ur_med = fields.Float(related="liasse_fiscale_new_id.contribution_med") + amount_ur_hdf = fields.Float(related="liasse_fiscale_new_id.contribution_hdf") + amount_fede_com = fields.Float(related="liasse_fiscale_new_id.contribution_com") + amount_fede_cae = fields.Float(related="liasse_fiscale_new_id.contribution_cae") + + is_payment = fields.Boolean("Paiements liés") # ------------------------------------------------------ # Constrains # ------------------------------------------------------ - @api.constrains('date_regul') + @api.constrains("date_regul") def _check_date_regul(self): - last_date = max(self.bordereau_id.invoice_ids.mapped('date_invoice')) - if self.date_regul > fields.Date.today() or \ - self.date_regul < last_date: - raise ValidationError("La date de régulation doit être " - "inférieure ou égale à la date du jour et " - "supérieure à la dernière date de " - "facturation liée au bordereau.") + last_date = max(self.bordereau_id.invoice_ids.mapped("date_invoice")) + if self.date_regul > fields.Date.today() or self.date_regul < last_date: + raise ValidationError( + _( + "La date de régulation doit être " + "inférieure ou égale à la date du jour et " + "supérieure à la dernière date de " + "facturation liée au bordereau." + ) + ) # ------------------------------------------------------ # Override ORM @@ -87,38 +91,47 @@ class ScopCotisationRegul(models.TransientModel): @api.model def default_get(self, fields): res = super(ScopCotisationRegul, self).default_get(fields) - bordereau_id = self.env['scop.bordereau'].browse( - self.env.context.get('active_id') + bordereau_id = self.env["scop.bordereau"].browse( + self.env.context.get("active_id") ) contribs = bordereau_id.invoice_ids.read_group( - [('id', 'in', bordereau_id.invoice_ids.ids)], - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + [("id", "in", bordereau_id.invoice_ids.ids)], + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) detail = "<table class='o_group o_inner_group'>" for contrib in contribs: - detail += ('<tr><td class="o_td_label font-weight-bold">' - + str(contrib.get('type_contribution_id')[1]) - + '</td><td style="width: 100%;">' - + str(contrib.get('amount_total_signed')) + '€</td>') - detail += '</table>' - payments = list(map( - lambda i: True if i.payment_move_line_ids else False, - bordereau_id.invoice_ids)) + detail += ( + '<tr><td class="o_td_label font-weight-bold">' + + str(contrib.get("type_contribution_id")[1]) + + '</td><td style="width: 100%;">' + + str(contrib.get("amount_total_signed")) + + "€</td>" + ) + detail += "</table>" + payments = list( + map( + lambda i: True if i.payment_move_line_ids else False, + bordereau_id.invoice_ids, + ) + ) if True in payments: is_payment = True else: is_payment = False - res.update({ - 'bordereau_id': bordereau_id.id, - 'partner_id': bordereau_id.partner_id.id, - 'liasse_fiscale_id': bordereau_id.liasse_fiscale_id.id, - 'year': bordereau_id.year_liasse, - 'type_assiette_retenu': bordereau_id.type_assiette, - 'montant_assiette': bordereau_id.montant_assiette, - 'amount_total_cotiz': bordereau_id.amount_total_cotiz, - 'detail': detail, - 'is_payment': is_payment, - }) + res.update( + { + "bordereau_id": bordereau_id.id, + "partner_id": bordereau_id.partner_id.id, + "liasse_fiscale_id": bordereau_id.liasse_fiscale_id.id, + "year": bordereau_id.year_liasse, + "type_assiette_retenu": bordereau_id.type_assiette, + "montant_assiette": bordereau_id.montant_assiette, + "amount_total_cotiz": bordereau_id.amount_total_cotiz, + "detail": detail, + "is_payment": is_payment, + } + ) return res # ------------------------------------------------------ @@ -126,32 +139,36 @@ class ScopCotisationRegul(models.TransientModel): # ------------------------------------------------------ def update_contribution(self): if not self.comment: - raise UserError("Vous devez renseigner un motif de " - "régularisation pour valider.") + raise UserError( + _("Vous devez renseigner un motif de " "régularisation pour valider.") + ) bordereau_id = self.bordereau_id partner_id = bordereau_id.partner_id # CREATE VERSION - bordereau_id.read(['amount_total_cotiz']) - self.env['scop.bordereau.version'].create({ - 'bordereau_id': bordereau_id.id, - 'date': self.date_regul, - 'comment': self.comment, - 'version': bordereau_id.version, - 'liasse_fiscale_id_old': bordereau_id.liasse_fiscale_id.id, - 'type_assiette': bordereau_id.type_assiette, - 'montant_assiette': bordereau_id.montant_assiette, - 'amount_total_cotiz': bordereau_id.amount_total_cotiz, - }) + bordereau_id.read(["amount_total_cotiz"]) + self.env["scop.bordereau.version"].create( + { + "bordereau_id": bordereau_id.id, + "date": self.date_regul, + "comment": self.comment, + "version": bordereau_id.version, + "liasse_fiscale_id_old": bordereau_id.liasse_fiscale_id.id, + "type_assiette": bordereau_id.type_assiette, + "montant_assiette": bordereau_id.montant_assiette, + "amount_total_cotiz": bordereau_id.amount_total_cotiz, + } + ) # CREATE REGUL contribs = bordereau_id.invoice_ids.read_group( - [('id', 'in', bordereau_id.invoice_ids.ids)], - ['type_contribution_id', 'amount_total_signed'], - ['type_contribution_id']) + [("id", "in", bordereau_id.invoice_ids.ids)], + ["type_contribution_id", "amount_total_signed"], + ["type_contribution_id"], + ) - ur_hdf = self.env.ref('cgscop_partner.riga_14232').id + ur_hdf = self.env.ref("cgscop_partner.riga_14232").id if partner_id.ur_id.id == ur_hdf: amount_ur = self.amount_ur_hdf product_ur = self.env.user.company_id.contribution_hdf_id @@ -162,87 +179,100 @@ class ScopCotisationRegul(models.TransientModel): account_ur = self.env.user.company_id.receivable_account_ur_med_id cotiz_type = { - self.env.ref('cgscop_partner.riga_14397').id: - [self.amount_cg, - self.env.user.company_id.contribution_cg_id, - self.env.user.company_id.contribution_journal_id, - partner_id.property_account_receivable_id.id], - self.env.ref('cgscop_partner.riga_14398').id: - [self.amount_fede_com, - self.env.user.company_id.contribution_fede_com_id, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - self.env.user.company_id.receivable_account_fede_com_id], - self.env.ref('cgscop_partner.cotiz_fede_cae').id: - [self.amount_fede_cae, - self.env.user.company_id.contribution_fede_cae_id, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - self.env.user.company_id.receivable_account_fede_cae_id], - self.env.ref('cgscop_partner.riga_14399').id: - [amount_ur, - product_ur, - self.env.user.company_id.contribution_ur_or_fede_journal_id, - account_ur], + self.env.ref("cgscop_partner.riga_14397").id: [ + self.amount_cg, + self.env.user.company_id.contribution_cg_id, + self.env.user.company_id.contribution_journal_id, + partner_id.property_account_receivable_id.id, + ], + self.env.ref("cgscop_partner.riga_14398").id: [ + self.amount_fede_com, + self.env.user.company_id.contribution_fede_com_id, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + self.env.user.company_id.receivable_account_fede_com_id, + ], + self.env.ref("cgscop_partner.cotiz_fede_cae").id: [ + self.amount_fede_cae, + self.env.user.company_id.contribution_fede_cae_id, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + self.env.user.company_id.receivable_account_fede_cae_id, + ], + self.env.ref("cgscop_partner.riga_14399").id: [ + amount_ur, + product_ur, + self.env.user.company_id.contribution_ur_or_fede_journal_id, + account_ur, + ], } - quarters = [bordereau_id.base_cotisation_cg.trimester_1, - bordereau_id.base_cotisation_cg.trimester_2, - bordereau_id.base_cotisation_cg.trimester_3, - bordereau_id.base_cotisation_cg.trimester_4] + quarters = [ + bordereau_id.base_cotisation_cg.trimester_1, + bordereau_id.base_cotisation_cg.trimester_2, + bordereau_id.base_cotisation_cg.trimester_3, + bordereau_id.base_cotisation_cg.trimester_4, + ] for contrib in contribs: - type_cotiz = contrib.get('type_contribution_id')[0] - amount_cotiz_old = contrib.get('amount_total_signed') + type_cotiz = contrib.get("type_contribution_id")[0] + amount_cotiz_old = contrib.get("amount_total_signed") amount_cotiz = cotiz_type.get(type_cotiz)[0] - refund_amount_total = self.env['scop.cotisation'].\ - round_to_closest_multiple(amount_cotiz_old - amount_cotiz, 4) + refund_amount_total = self.env["scop.cotisation"].round_to_closest_multiple( + amount_cotiz_old - amount_cotiz, 4 + ) product = cotiz_type.get(type_cotiz)[1] type_invoice = False if refund_amount_total < 0: - type_invoice = 'out_invoice' + type_invoice = "out_invoice" refund_amount_total *= -1 elif refund_amount_total > 0: - type_invoice = 'out_refund' + type_invoice = "out_refund" refund_amount = refund_amount_total / bordereau_id.nb_quarter if type_invoice: - for i in range(0, bordereau_id.nb_quarter): + for i in range(0, int(bordereau_id.nb_quarter)): if self.date_regul < quarters[i]: date_due = quarters[i] else: date_due = self.date_regul - refund = self.env['account.invoice'].create({ - 'partner_id': partner_id.id, - 'journal_id': cotiz_type.get(type_cotiz)[2].id, - 'account_id': partner_id.property_account_receivable_id.id, - 'type': type_invoice, - 'date_invoice': self.date_regul, - 'date': self.date_regul, - 'state': 'draft', - 'number': False, - 'origin': bordereau_id.name, - 'name': self.comment, - 'bordereau_id': bordereau_id.id, - 'is_contribution': True, - 'year': bordereau_id.year, - 'liasse_fiscale_id': bordereau_id.liasse_fiscale_id.id, - 'type_contribution_id': type_cotiz, - 'payment_mode_id': bordereau_id.payment_mode_id.id, - 'date_due': date_due, - 'cotiz_quarter': i+1, - }) - self.env['account.invoice.line'].create({ - 'name': self.comment + " - " + str(i+1) + "/" + str(bordereau_id.nb_quarter), - 'invoice_id': refund.id, - 'product_id': product.id, - 'account_id': product.property_account_income_id.id, - 'price_unit': refund_amount - }) - bordereau_id.update({ - 'liasse_fiscale_id': self.liasse_fiscale_new_id.id - }) - bordereau_id.invoice_ids.update({ - 'liasse_fiscale_id': self.liasse_fiscale_new_id.id - }) + refund = self.env["account.invoice"].create( + { + "partner_id": partner_id.id, + "journal_id": cotiz_type.get(type_cotiz)[2].id, + "account_id": partner_id.property_account_receivable_id.id, + "type": type_invoice, + "date_invoice": self.date_regul, + "date": self.date_regul, + "state": "draft", + "number": False, + "origin": bordereau_id.name, + "name": self.comment, + "bordereau_id": bordereau_id.id, + "is_contribution": True, + "year": bordereau_id.year, + "liasse_fiscale_id": bordereau_id.liasse_fiscale_id.id, + "type_contribution_id": type_cotiz, + "payment_mode_id": bordereau_id.payment_mode_id.id, + "date_due": date_due, + "cotiz_quarter": i + 1, + } + ) + self.env["account.invoice.line"].create( + { + "name": self.comment + + " - " + + str(i + 1) + + "/" + + bordereau_id.nb_quarter, + "invoice_id": refund.id, + "product_id": product.id, + "account_id": product.property_account_income_id.id, + "price_unit": refund_amount, + } + ) + bordereau_id.update({"liasse_fiscale_id": self.liasse_fiscale_new_id.id}) + bordereau_id.invoice_ids.update( + {"liasse_fiscale_id": self.liasse_fiscale_new_id.id} + ) diff --git a/wizard/scop_cotisation_cg_regul_wizard.xml b/wizard/scop_cotisation_cg_regul_wizard.xml index b4a258d27a081f18307278a82d31e235820b3e26..f1b56385d9e613877d5fdf5d808cc923962c38a6 100644 --- a/wizard/scop_cotisation_cg_regul_wizard.xml +++ b/wizard/scop_cotisation_cg_regul_wizard.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <odoo> <!-- Copyright 2020 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> @@ -10,75 +10,145 @@ <field name="arch" type="xml"> <form string="Régularisation Cotisation"> <sheet> - <field name="is_payment" invisible="1"/> + <field name="is_payment" invisible="1" /> <div class="row"> <div class="col-6"> - <label for="bordereau_id"/> + <label for="bordereau_id" /> <h1> - <field name="bordereau_id" options='{"no_open": True}'/> + <field + name="bordereau_id" + options='{"no_open": True}' + /> </h1> </div> <div class="col-6"> - <label for="partner_id"/> + <label for="partner_id" /> <h3> - <field name="partner_id" options='{"no_open": True}'/> + <field + name="partner_id" + options='{"no_open": True}' + /> </h3> </div> </div> <div class="row"> <div class="col-6"> <group string="Données initiales" class="text-muted"> - <field name="liasse_fiscale_id" readonly="1" options='{"no_open": True}'/> - <field name="year" readonly="1"/> - <field name="type_assiette_retenu" readonly="1"/> - <field name="montant_assiette" readonly="1"/> - <field name="amount_total_cotiz" class="font-weight-bold" readonly="1"/> + <field + name="liasse_fiscale_id" + readonly="1" + options='{"no_open": True}' + /> + <field name="year" readonly="1" /> + <field name="type_assiette_retenu" readonly="1" /> + <field name="montant_assiette" readonly="1" /> + <field + name="amount_total_cotiz" + class="font-weight-bold" + readonly="1" + /> </group> - <field name="detail" class="text-muted" readonly="1" widget="html"/> + <field + name="detail" + class="text-muted" + readonly="1" + widget="html" + /> </div> <div class="col-6"> <group string="Nouveaux calculs"> - <field name="date_regul" required="1"/> - <separator/> - <field name="liasse_fiscale_new_id" domain="[('partner_id', '=', partner_id)]" - options='{"no_create": True}' help="Nouvelle liasse fiscale à prendre en compte"/> + <field name="date_regul" required="1" /> + <separator /> + <field + name="liasse_fiscale_new_id" + domain="[('partner_id', '=', partner_id)]" + options='{"no_create": True}' + help="Nouvelle liasse fiscale à prendre en compte" + /> </group> <group> - <field name="type_id_new" attrs="{'invisible': [('liasse_fiscale_new_id', '=', False)]}"/> - <field name="source_new" attrs="{'invisible': [('liasse_fiscale_new_id', '=', False)]}"/> + <field + name="type_id_new" + attrs="{'invisible': [('liasse_fiscale_new_id', '=', False)]}" + /> + <field + name="source_new" + attrs="{'invisible': [('liasse_fiscale_new_id', '=', False)]}" + /> </group> <group> - <field name="type_assiette_new" attrs="{'invisible': [('amount_cg', '=', 0.0)]}" readonly="1"/> - <field name="montant_assiette_new" attrs="{'invisible': [('amount_cg', '=', 0.0)]}" readonly="1"/> + <field + name="type_assiette_new" + attrs="{'invisible': [('amount_cg', '=', 0.0)]}" + readonly="1" + /> + <field + name="montant_assiette_new" + attrs="{'invisible': [('amount_cg', '=', 0.0)]}" + readonly="1" + /> </group> <group> - <field name="amount_cg" attrs="{'invisible': [('amount_cg', '=', 0.0)]}" readonly="1"/> - <field name="amount_fede_com" attrs="{'invisible': [('amount_fede_com', '=', 0.0)]}" readonly="1"/> - <field name="amount_fede_cae" attrs="{'invisible': [('amount_fede_cae', '=', 0.0)]}" readonly="1"/> - <field name="amount_ur_hdf" attrs="{'invisible': [('amount_ur_hdf', '=', 0.0)]}" readonly="1"/> - <field name="amount_ur_med" attrs="{'invisible': [('amount_ur_med', '=', 0.0)]}" readonly="1"/> + <field + name="amount_cg" + attrs="{'invisible': [('amount_cg', '=', 0.0)]}" + readonly="1" + /> + <field + name="amount_fede_com" + attrs="{'invisible': [('amount_fede_com', '=', 0.0)]}" + readonly="1" + /> + <field + name="amount_fede_cae" + attrs="{'invisible': [('amount_fede_cae', '=', 0.0)]}" + readonly="1" + /> + <field + name="amount_ur_hdf" + attrs="{'invisible': [('amount_ur_hdf', '=', 0.0)]}" + readonly="1" + /> + <field + name="amount_ur_med" + attrs="{'invisible': [('amount_ur_med', '=', 0.0)]}" + readonly="1" + /> </group> - <label for="comment" attrs="{'invisible': [('amount_cg', '=', 0.0)]}"/> - <field name="comment" attrs="{'invisible': [('amount_cg', '=', 0.0)]}"/> + <label + for="comment" + attrs="{'invisible': [('amount_cg', '=', 0.0)]}" + /> + <field + name="comment" + attrs="{'invisible': [('amount_cg', '=', 0.0)]}" + /> </div> </div> </sheet> <footer> - <button name="update_contribution" type="object" string="Régulariser le bordereau" class="oe_highlight"/> - <button string="Annuler" special="cancel" class="oe_link"/> + <button + name="update_contribution" + type="object" + string="Régulariser le bordereau" + class="oe_highlight" + /> + <button string="Annuler" special="cancel" class="oe_link" /> </footer> </form> </field> </record> - <record id="scop_cotisation_regul_wizard_act_window" model="ir.actions.act_window"> + <record + id="scop_cotisation_regul_wizard_act_window" + model="ir.actions.act_window" + > <field name="name">Régularisation Cotisation</field> <field name="type">ir.actions.act_window</field> <field name="res_model">scop.cotisation.regul.wizard</field> - <field name="view_type">form</field> <field name="view_mode">form</field> <field name="target">new</field> </record> </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/wizard/scop_cotisation_cg_wizard.py b/wizard/scop_cotisation_cg_wizard.py index bef19b43687a4e8f58f35279ac9ae9781a11efbb..3e3d30f5243f4002d70ea7e033e4dd1db7f39d4d 100644 --- a/wizard/scop_cotisation_cg_wizard.py +++ b/wizard/scop_cotisation_cg_wizard.py @@ -3,116 +3,121 @@ import logging -from odoo import api, fields, models, exceptions +from odoo import _, api, exceptions, fields, models _logger = logging.getLogger(__name__) class ScopCotisationWizard(models.TransientModel): - _name = 'scop.cotisation.cg.wizard' + _name = "scop.cotisation.cg.wizard" _description = "Wizard: Génération des cotisations nouveaux adhérents" - year = fields.Char( - string='Année', - required=True) + year = fields.Char(string="Année", required=True) cotisation_cg_id = fields.Many2one( - comodel_name='scop.cotisation.cg', - string='Base de cotisation') + comodel_name="scop.cotisation.cg", string="Base de cotisation" + ) nb_quarter = fields.Selection( - string='Nombre de trimestres de cotisation', - selection=[(1, '1'), - (2, '2'), - (3, '3'), - (4, '4')], - default='4', - required=True) - type = fields.Selection([ - ('all', 'Toutes les coop nouvelles adhérentes'), - ('selected', 'Sélectionner des coop')], - string='Type de création', - default='all' + string="Nombre de trimestres de cotisation", + selection=[("1", "1"), ("2", "2"), ("3", "3"), ("4", "4")], + default="4", + required=True, ) - partner_ids = fields.Many2many( - comodel_name='res.partner', - string='Coopératives' + type = fields.Selection( + [ + ("all", "Toutes les coop nouvelles adhérentes"), + ("selected", "Sélectionner des coop"), + ], + string="Type de création", + default="all", ) - date = fields.Date('Date de cotisation', default=fields.Date.today()) + partner_ids = fields.Many2many(comodel_name="res.partner", string="Coopératives") + date = fields.Date("Date de cotisation", default=fields.Date.today()) # ------------------------------------------------------ # Button function # ------------------------------------------------------ - @api.onchange('type') + @api.onchange("type") def onchange_domain_partner_ids(self): - if self.type == 'selected': - id_cotisation_cg = self.env.context['id_cotisation_cg'] + if self.type == "selected": + id_cotisation_cg = self.env.context["id_cotisation_cg"] invoiced_members = self.cotisation_cg_id.browse( - id_cotisation_cg).invoice_ids.mapped('partner_id') - - res = {'domain': { - 'partner_ids': [ - ('is_company', '=', True), - ('type', '!=', 'facility'), - ('id', 'not in', invoiced_members.mapped('id'))] - }} + id_cotisation_cg + ).invoice_ids.mapped("partner_id") + + res = { + "domain": { + "partner_ids": [ + ("is_company", "=", True), + ("type", "!=", "facility"), + ("id", "not in", invoiced_members.mapped("id")), + ] + } + } return res # ------------------------------------------------------ # Button function # ------------------------------------------------------ - @api.multi def cotiz_generate_new_adherents(self): - if not self.env.user.company_id.is_contribution_cg: + if not self.env.company.is_contribution_cg: raise exceptions.UserError( - "La gestion des cotisations CGScop n'est pas configurée.") - - if self.type == 'selected': + _("La gestion des cotisations CGScop n'est pas configurée.") + ) + if self.type == "selected": members = self.partner_ids else: members = self.cotisation_cg_id.get_new_members(self.date) - invoiced_members = self.cotisation_cg_id. \ - invoice_ids.mapped('partner_id') - + invoiced_members = self.cotisation_cg_id.invoice_ids.mapped("partner_id") members_to_invoice = members - invoiced_members if len(members_to_invoice) > 0: message = ( - "<h3>Bordereaux " + str(self.year) + - "</h3> <hr/>" + - "<br/>Bordereaux nouveaux adhérents à générer : " + - str(len(members_to_invoice)) + - "<p>Les appels de cotisation sont en cours de " - "création...</p> " + "<h3>Bordereaux " + + str(self.year) + + "</h3> <hr/>" + + "<br/>Bordereaux nouveaux adhérents à générer : " + + str(len(members_to_invoice)) + + "<p>Les appels de cotisation sont en cours de " + "création...</p> " ) - message_id = self.env['message.wizard'].create( - {'message': message}) # Job queue - batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + - " Génération des bordereaux " + - str(self.cotisation_cg_id.year)) - batch = self.env['queue.job.batch'].get_new_batch(batch_name) + batch_name = ( + fields.Datetime.to_string(fields.Datetime.now()) + + " Génération des bordereaux " + + str(self.cotisation_cg_id.year) + ) + batch = self.env["queue.job.batch"].get_new_batch(batch_name) for member in members_to_invoice: liasse_id = self.cotisation_cg_id.get_liasse(member) self.cotisation_cg_id.with_context( job_batch=batch ).with_delay().create_bordereau( - member=member, liasse=liasse_id, - nb_quarter=self.nb_quarter, date=self.date) + member=member, + liasse=liasse_id, + nb_quarter=self.nb_quarter, + date=self.date, + ) batch.enqueue() else: - message = ("<p class='text-center'>Tous les bordereaux pour les " - "coops qui ont adhéré cette année avant le %s ont " - "déjà été créés !</p>" % self.date.strftime("%d/%m")) - message_id = self.env['message.wizard'].create( - {'message': message}) + message = ( + "<p class='text-center'>Tous les bordereaux pour les " + "coops qui ont adhéré cette année avant le %s ont " + "déjà été créés !</p>" % self.date.strftime("%d/%m") + ) return { - 'name': 'Génération des appels de cotisation nouveaux adhérents', - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'message.wizard', - 'res_id': message_id.id, - 'target': 'new' + "type": "ir.actions.act_window.message", + "title": _("Génération des appels de cotisation nouveaux adhérents"), + "is_html_message": True, + "message": _(message), + "close_button_title": False, + "buttons": [ + { + "type": "ir.actions.act_window_close", + "name": "Fermer", + }, + ], } diff --git a/wizard/scop_cotisation_cg_wizard.xml b/wizard/scop_cotisation_cg_wizard.xml index 5429634653ea2769d705fc8b053977480f1ed1fd..33c52e8483a0347a6d4155abebdb686e507e3b58 100644 --- a/wizard/scop_cotisation_cg_wizard.xml +++ b/wizard/scop_cotisation_cg_wizard.xml @@ -1,7 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- Copyright 2021 Le Filament License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> <data> @@ -11,26 +10,38 @@ <field name="arch" type="xml"> <form string="Générer les cotisation pour les nouveaux adhérents"> <group> - <field name="year" required="1" invisible="1"/> - <field name="date" required="1"/> - <field name="nb_quarter" required="1"/> - <field name="type" widget="radio"/> - <field name="partner_ids" attrs="{'invisible': [('type', '=', 'all')]}" widget="many2many_tags" options="{'no_create': True, 'no_open': True}"/> + <field name="year" required="1" invisible="1" /> + <field name="date" required="1" /> + <field name="nb_quarter" required="1" /> + <field name="type" widget="radio" /> + <field + name="partner_ids" + attrs="{'invisible': [('type', '=', 'all')]}" + widget="many2many_tags" + options="{'no_create': True, 'no_open': True}" + /> </group> <footer> - <button name="cotiz_generate_new_adherents" type="object" - string="Générer les cotisations" class="oe_highlight"/> - <button special="cancel" string="Cancel"/> + <button + name="cotiz_generate_new_adherents" + type="object" + string="Générer les cotisations" + class="oe_highlight" + /> + <button special="cancel" string="Cancel" /> </footer> </form> </field> </record> - <record model="ir.actions.act_window" id="action_genere_cotisation_cg_new_adherents"> + <record + model="ir.actions.act_window" + id="action_genere_cotisation_cg_new_adherents" + > <field name="name">Générer les cotisations nouveaux adhérents</field> <field name="res_model">scop.cotisation.cg.wizard</field> <field name="view_mode">form</field> - <field name="view_id" ref="scop_cotisation_cg_wizard_form_view"/> + <field name="view_id" ref="scop_cotisation_cg_wizard_form_view" /> <field name="target">new</field> </record>