diff --git a/.docker_files/main/__manifest__.py b/.docker_files/main/__manifest__.py index 1fa24a63..00e518fb 100644 --- a/.docker_files/main/__manifest__.py +++ b/.docker_files/main/__manifest__.py @@ -50,7 +50,8 @@ "canada_bank_transfer", "hr_expense_tax_adjustment", "invoice_currency_validation", - # "invoice_fiscal_position_required", # FIX ME: Conflict with UT of account_invoice_constraint_chronology OCA Module + # FIX ME: Conflict with UT of account_invoice_constraint_chronology OCA Module + # "invoice_fiscal_position_required", "invoice_intercompany_compatible", "invoice_list_email", "invoice_mass_mailing_with_layout", diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..15d225b7 --- /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,F821 +per-file-ignores= + __init__.py:F401 \ No newline at end of file diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..2894822e --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,36 @@ +name: pre-commit + +on: + pull_request: + branches: + - "14.0*" + push: + branches: + - "14.0" + +jobs: + pre-commit: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v2 + with: + python-version: "3.11" + - name: Get python version + run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV + - uses: actions/cache@v1 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit + run: pre-commit run --all-files --show-diff-on-failure --color=always + - name: Check that all files generated by pre-commit are in git + run: | + newfiles="$(git ls-files --others --exclude-from=.gitignore)" + if [ "$newfiles" != "" ] ; then + echo "Please check-in the following files:" + echo "$newfiles" + exit 1 + fi \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..004b7146 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +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$| + # Don't bother non-technical authors with formatting issues in docs + readme/.*\.(rst|md)$| + # Ignore build and dist directories in addons + /build/|/dist/| + # 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: https://github.com/PyCQA/flake8 + rev: 3.8.3 + hooks: + - id: flake8 + name: flake8 + additional_dependencies: ["flake8-bugbear==20.1.4"] \ No newline at end of file diff --git a/.unported_addons/account_budget_balance/README.rst b/.unported_addons/account_budget_balance/README.rst deleted file mode 100644 index b8bdc9ea..00000000 --- a/.unported_addons/account_budget_balance/README.rst +++ /dev/null @@ -1,19 +0,0 @@ -Account Budget Balance -====================== -This module adds a `Balance` column to the budget lines. - -.. image:: static/description/budget_form.png - -The field is computed as follow: - -.. - - Planned Amount - Practical Amount = Balance Amount - -The field is available in the `Budget Analysis` report. - -.. image:: static/description/budget_line_pivot.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/account_budget_balance/__init__.py b/.unported_addons/account_budget_balance/__init__.py deleted file mode 100644 index 21228467..00000000 --- a/.unported_addons/account_budget_balance/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/account_budget_balance/__manifest__.py b/.unported_addons/account_budget_balance/__manifest__.py deleted file mode 100644 index 1f5c04d8..00000000 --- a/.unported_addons/account_budget_balance/__manifest__.py +++ /dev/null @@ -1,21 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Account Budget Balance', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Add the balance amount to the budget lines', - 'depends': [ - 'account_budget', - ], - 'data': [ - 'views/crossovered_budget.xml', - 'views/crossovered_budget_lines.xml', - ], - 'installable': False, -} diff --git a/.unported_addons/account_budget_balance/i18n/fr.po b/.unported_addons/account_budget_balance/i18n/fr.po deleted file mode 100644 index b5fcfbd3..00000000 --- a/.unported_addons/account_budget_balance/i18n/fr.po +++ /dev/null @@ -1,32 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * account_budget_balance -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-13 19:47+0000\n" -"PO-Revision-Date: 2019-06-13 19:47+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: account_budget_balance -#: model:ir.model.fields,field_description:account_budget_balance.field_crossovered_budget_lines__balance -#: model_terms:ir.ui.view,arch_db:account_budget_balance.budget_form_with_balance -msgid "Balance" -msgstr "Balance" - -#. module: account_budget_balance -#: model:ir.model,name:account_budget_balance.model_crossovered_budget_lines -msgid "Budget Line" -msgstr "" - -#. module: account_budget_balance -#: model:ir.model.fields,help:account_budget_balance.field_crossovered_budget_lines__balance -msgid "The balance amount is equal to the planned amount minus the practical amount." -msgstr "Le montant de balance est égal au montant prévu moins le montant réel." diff --git a/.unported_addons/account_budget_balance/models/__init__.py b/.unported_addons/account_budget_balance/models/__init__.py deleted file mode 100644 index 639ad51b..00000000 --- a/.unported_addons/account_budget_balance/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import crossovered_budget_lines diff --git a/.unported_addons/account_budget_balance/models/crossovered_budget_lines.py b/.unported_addons/account_budget_balance/models/crossovered_budget_lines.py deleted file mode 100644 index 32f58aad..00000000 --- a/.unported_addons/account_budget_balance/models/crossovered_budget_lines.py +++ /dev/null @@ -1,40 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, fields, models - - -class CrossoveredBudgetLines(models.Model): - - _inherit = "crossovered.budget.lines" - - balance = fields.Monetary( - compute="_compute_balance_amount", - string="Balance", - help="The balance amount is equal to the planned amount " - "minus the practical amount." - ) - - @api.depends('planned_amount', 'practical_amount') - def _compute_balance_amount(self): - for line in self: - line.balance = line.planned_amount - line.practical_amount - - @api.model - def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): - """Allow reading the balance amount with group read. - - This is inspired by what is done in the module account_budget with the fields - practical_amount, theoritical_amount and percentage. - """ - result = super().read_group( - domain, fields, groupby, - offset=offset, limit=limit, orderby=orderby, lazy=lazy - ) - if 'balance' in fields: - for group_line in result: - group_domain = group_line.get('__domain') or domain - lines_that_compose_group = self.search(group_domain) - group_line['balance'] = sum(lines_that_compose_group.mapped('balance')) - - return result diff --git a/.unported_addons/account_budget_balance/static/description/budget_form.png b/.unported_addons/account_budget_balance/static/description/budget_form.png deleted file mode 100644 index 27e09857..00000000 Binary files a/.unported_addons/account_budget_balance/static/description/budget_form.png and /dev/null differ diff --git a/.unported_addons/account_budget_balance/static/description/budget_line_pivot.png b/.unported_addons/account_budget_balance/static/description/budget_line_pivot.png deleted file mode 100644 index ac57b3dc..00000000 Binary files a/.unported_addons/account_budget_balance/static/description/budget_line_pivot.png and /dev/null differ diff --git a/.unported_addons/account_budget_balance/static/description/icon.png b/.unported_addons/account_budget_balance/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/account_budget_balance/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/account_budget_balance/tests/__init__.py b/.unported_addons/account_budget_balance/tests/__init__.py deleted file mode 100644 index d2ac44f2..00000000 --- a/.unported_addons/account_budget_balance/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/account_budget_balance/tests/test_balance_read_group.py b/.unported_addons/account_budget_balance/tests/test_balance_read_group.py deleted file mode 100644 index abfd6f71..00000000 --- a/.unported_addons/account_budget_balance/tests/test_balance_read_group.py +++ /dev/null @@ -1,93 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from datetime import datetime, timedelta -from odoo.tests import common - - -class TestBalanceReadGroup(common.SavepointCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.budget_1 = cls.env['crossovered.budget'].create({ - 'name': 'Budget Test 1', - 'date_from': datetime.now(), - 'date_to': datetime.now() + timedelta(365), - }) - - cls.budget_2 = cls.env['crossovered.budget'].create({ - 'name': 'Budget Test 2', - 'date_from': datetime.now(), - 'date_to': datetime.now() + timedelta(365), - }) - - cls.account_1 = cls.env['account.analytic.account'].create({'name': 'Account 1'}) - cls.account_2 = cls.env['account.analytic.account'].create({'name': 'Account 2'}) - cls.account_3 = cls.env['account.analytic.account'].create({'name': 'Account 3'}) - - cls.budget_line_1 = cls.env['crossovered.budget.lines'].create({ - 'crossovered_budget_id': cls.budget_1.id, - 'analytic_account_id': cls.account_1.id, - 'planned_amount': 1000, - 'date_from': cls.budget_1.date_from, - 'date_to': cls.budget_1.date_to, - }) - - cls.budget_line_2 = cls.env['crossovered.budget.lines'].create({ - 'crossovered_budget_id': cls.budget_1.id, - 'analytic_account_id': cls.account_2.id, - 'planned_amount': 2000, - 'date_from': cls.budget_1.date_from, - 'date_to': cls.budget_1.date_to, - }) - - cls.budget_line_3 = cls.env['crossovered.budget.lines'].create({ - 'crossovered_budget_id': cls.budget_2.id, - 'analytic_account_id': cls.account_3.id, - 'planned_amount': 5000, - 'date_from': cls.budget_2.date_from, - 'date_to': cls.budget_2.date_to, - }) - - cls.line_1 = cls.env['account.analytic.line'].create({ - 'account_id': cls.account_1.id, - 'name': '/', - 'amount': 100, - }) - - cls.line_2 = cls.env['account.analytic.line'].create({ - 'account_id': cls.account_2.id, - 'name': '/', - 'amount': 200, - }) - - cls.line_3 = cls.env['account.analytic.line'].create({ - 'account_id': cls.account_3.id, - 'name': '/', - 'amount': 500, - }) - - cls.budget_lines = cls.budget_line_1 | cls.budget_line_2 | cls.budget_line_3 - cls.search_domain = [('id', 'in', cls.budget_lines.ids)] - - def test_read_group_by_budget(self): - result = self.env['crossovered.budget.lines'].read_group( - self.search_domain, ['balance'], ['crossovered_budget_id'], - orderby='crossovered_budget_id asc' - ) - - assert len(result) == 2 - assert result[0]['balance'] == 2700 # 1000 + 2000 - 100 - 200 - assert result[1]['balance'] == 4500 # 5000 - 500 - - def test_read_group_by_analytic_account(self): - result = self.env['crossovered.budget.lines'].read_group( - self.search_domain, ['balance'], ['analytic_account_id'], - orderby='analytic_account_id asc' - ) - - assert len(result) == 3 - assert result[0]['balance'] == 900 # 1000 - 100 - assert result[1]['balance'] == 1800 # 2000 - 200 - assert result[2]['balance'] == 4500 # 5000 - 500 diff --git a/.unported_addons/account_budget_balance/views/crossovered_budget.xml b/.unported_addons/account_budget_balance/views/crossovered_budget.xml deleted file mode 100644 index 7ece170f..00000000 --- a/.unported_addons/account_budget_balance/views/crossovered_budget.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Budget Form: add balance amount - crossovered.budget - - - - - - - - - diff --git a/.unported_addons/account_budget_balance/views/crossovered_budget_lines.xml b/.unported_addons/account_budget_balance/views/crossovered_budget_lines.xml deleted file mode 100644 index 94a577f6..00000000 --- a/.unported_addons/account_budget_balance/views/crossovered_budget_lines.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - Budget Line Form: add balance amount - crossovered.budget.lines - - - - - - - - - - Budget Line List: add balance amount - crossovered.budget.lines - - - - - - - - - - Budget Line Pivot: add balance amount - crossovered.budget.lines - - - - - - - - - - Budget Line Graph: add balance amount - crossovered.budget.lines - - - - - - - - - diff --git a/.unported_addons/account_manual_entry_restricted/README.rst b/.unported_addons/account_manual_entry_restricted/README.rst deleted file mode 100644 index 1661ea68..00000000 --- a/.unported_addons/account_manual_entry_restricted/README.rst +++ /dev/null @@ -1,51 +0,0 @@ -Account Manual Entry Restricted -=============================== - -.. contents:: Table of Contents - -Context -------- -In vanilla Odoo, a user with basic access may create and post journal entries manually. - -As accountant / controller, you might want to keep control over some specific accounts. -You do not want people to accidentaly write in these accounts. - -Summary -------- -This module adds a field `Entry Restriction` on accounts. - -.. image:: static/description/account_form.png - -This field allows to select one or many user groups. - -These groups are allowed to post manual journal entries with this account. -Other groups are forbidden. - -If the field is empty, then no restriction is applied on this account. - -Automatic Entries -~~~~~~~~~~~~~~~~~ -These restrictions do not apply for journal entries generated automatically -for invoices, payments, expenses, etc. - -Usage ------ -As member of the group `Accounting / Advisor`, I go to the form view of an account. - -I select the group `Accounting / Advisor`. - -.. image:: static/description/account_form.png - -Manual Entries -­~~~~~~~~~~~~~~ -As member of the group `Accounting / User`, I create a new journal entry with the restricted account. - -.. image:: static/description/journal_entry.png - -When I click on `Post`, a blocking message appears. - -.. image:: static/description/journal_entry_message.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/account_manual_entry_restricted/__init__.py b/.unported_addons/account_manual_entry_restricted/__init__.py deleted file mode 100644 index 21228467..00000000 --- a/.unported_addons/account_manual_entry_restricted/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/account_manual_entry_restricted/__manifest__.py b/.unported_addons/account_manual_entry_restricted/__manifest__.py deleted file mode 100644 index ee9f9d07..00000000 --- a/.unported_addons/account_manual_entry_restricted/__manifest__.py +++ /dev/null @@ -1,20 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Account Manual Entry Restricted', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Restrict manual journal entries per account', - 'depends': [ - 'account', - ], - 'data': [ - 'views/account.xml', - ], - 'installable': False, -} diff --git a/.unported_addons/account_manual_entry_restricted/i18n/fr.po b/.unported_addons/account_manual_entry_restricted/i18n/fr.po deleted file mode 100644 index 966f94be..00000000 --- a/.unported_addons/account_manual_entry_restricted/i18n/fr.po +++ /dev/null @@ -1,49 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * account_manual_entry_restricted -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-10 21:29+0000\n" -"PO-Revision-Date: 2019-06-10 21:29+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: account_manual_entry_restricted -#: code:addons/account_manual_entry_restricted/models.py:33 -#, python-format -msgid "Access right error:\n" -"\n" -"Only the following user group(s) are authorized to post in the account {account}:\n" -"\n" -"{groups}\n" -"\n" -"Please contact your administrator." -msgstr "Erreur de droits d'accès :\n" -"\n" -"Seul(s) le(s) groupe(s) de droits suivant(s) sont autorisés à saisir dans le compte {account} :\n" -"\n" -"{groups}\n" -"\n" -"Veuillez contacter votre administrateur." - -#. module: account_manual_entry_restricted -#: model:ir.model,name:account_manual_entry_restricted.model_account_account -msgid "Account" -msgstr "" - -#. module: account_manual_entry_restricted -#: model:ir.model.fields,field_description:account_manual_entry_restricted.field_account_account__manual_entry_group_ids -msgid "Entry Restriction" -msgstr "Restriction saisie" - -#. module: account_manual_entry_restricted -#: model:ir.model,name:account_manual_entry_restricted.model_account_move -msgid "Journal Entries" -msgstr "" diff --git a/.unported_addons/account_manual_entry_restricted/models.py b/.unported_addons/account_manual_entry_restricted/models.py deleted file mode 100644 index 1a0e8d3f..00000000 --- a/.unported_addons/account_manual_entry_restricted/models.py +++ /dev/null @@ -1,57 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, fields, models, _ -from odoo.exceptions import ValidationError - - -class Account(models.Model): - - _inherit = 'account.account' - - manual_entry_group_ids = fields.Many2many( - 'res.groups', - 'account_manual_entry_group_rel', - 'account_id', - 'group_id', - 'Entry Restriction', - ) - - -class JournalEntry(models.Model): - - _inherit = 'account.move' - - def _check_manual_entry_restrictions(self): - restricted_accounts = self.mapped('line_ids.account_id').filtered( - lambda a: a.manual_entry_group_ids) - - for account in restricted_accounts: - allowed_groups = account.manual_entry_group_ids - user_is_forbidden = not (allowed_groups & self.env.user.groups_id) - if user_is_forbidden: - raise ValidationError(_( - 'Access right error:\n\n' - 'Only the following user group(s) are authorized to post in the account ' - '{account}:\n\n' - '{groups}' - '\n\n' - 'Please contact your administrator.' - ).format( - account=account.display_name, - groups='\n'.join(['- {}'.format(g.display_name) for g in allowed_groups]) - )) - - def action_post(self): - """Verify the contrains on manual journal entries. - - This method is a wrapper around the method post. - - It is only called by the button from the form - view of account.move. - - The method post is called directly for automatted entries - (invoices, payments, expenses, etc). - """ - self._check_manual_entry_restrictions() - return super().action_post() diff --git a/.unported_addons/account_manual_entry_restricted/static/description/account_form.png b/.unported_addons/account_manual_entry_restricted/static/description/account_form.png deleted file mode 100644 index 7c8514e3..00000000 Binary files a/.unported_addons/account_manual_entry_restricted/static/description/account_form.png and /dev/null differ diff --git a/.unported_addons/account_manual_entry_restricted/static/description/icon.png b/.unported_addons/account_manual_entry_restricted/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/account_manual_entry_restricted/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/account_manual_entry_restricted/static/description/journal_entry.png b/.unported_addons/account_manual_entry_restricted/static/description/journal_entry.png deleted file mode 100644 index 2e9578f9..00000000 Binary files a/.unported_addons/account_manual_entry_restricted/static/description/journal_entry.png and /dev/null differ diff --git a/.unported_addons/account_manual_entry_restricted/static/description/journal_entry_message.png b/.unported_addons/account_manual_entry_restricted/static/description/journal_entry_message.png deleted file mode 100644 index 737cb455..00000000 Binary files a/.unported_addons/account_manual_entry_restricted/static/description/journal_entry_message.png and /dev/null differ diff --git a/.unported_addons/account_manual_entry_restricted/tests/__init__.py b/.unported_addons/account_manual_entry_restricted/tests/__init__.py deleted file mode 100644 index d2ac44f2..00000000 --- a/.unported_addons/account_manual_entry_restricted/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/account_manual_entry_restricted/tests/test_manual_entry_restriction.py b/.unported_addons/account_manual_entry_restricted/tests/test_manual_entry_restriction.py deleted file mode 100644 index c10b32ce..00000000 --- a/.unported_addons/account_manual_entry_restricted/tests/test_manual_entry_restriction.py +++ /dev/null @@ -1,68 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -import pytest -from odoo.tests import common -from odoo.exceptions import ValidationError - - -class TestManualEntryRestriction(common.SavepointCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.group_1 = cls.env['res.groups'].create({'name': 'Group 1'}) - cls.group_2 = cls.env['res.groups'].create({'name': 'Group 2'}) - cls.journal = cls.env['account.journal'].search([], limit=1) - cls.account_1 = cls.env['account.account'].create({ - 'name': 'Account 1', - 'code': '111111', - 'user_type_id': cls.env.ref('account.data_account_type_fixed_assets').id, - }) - cls.account_2 = cls.env['account.account'].create({ - 'name': 'Account 2', - 'code': '111112', - 'user_type_id': cls.env.ref('account.data_account_type_fixed_assets').id, - }) - cls.move = cls.env['account.move'].create({ - 'journal_id': cls.journal.id, - 'line_ids': [ - (0, 0, { - 'account_id': cls.account_1.id, - 'name': '/', - 'debit': 100, - }), - (0, 0, { - 'account_id': cls.account_2.id, - 'name': '/', - 'credit': 100, - }) - ] - }) - - def test_if_no_restriction__constraint_not_raised(self): - self.move.action_post() - assert self.move.state == 'posted' - - def test_if_user_not_member_of_group__constraint_raised(self): - self.account_1.manual_entry_group_ids = self.group_1 - with pytest.raises(ValidationError): - self.move.action_post() - - def test_if_user_member_of_group__constraint_not_raised(self): - self.env.user.groups_id = self.group_1 - self.account_1.manual_entry_group_ids = self.group_1 - self.move.action_post() - assert self.move.state == 'posted' - - def test_if_multiple_groups__user_must_be_member_of_one_group(self): - self.env.user.groups_id = self.group_1 - self.account_1.manual_entry_group_ids = self.group_1 | self.group_2 - self.move.action_post() - assert self.move.state == 'posted' - - def test_if_post_called_directly__constraint_not_raised(self): - """Test that automatic entries are not restricted.""" - self.account_1.manual_entry_group_ids = self.group_1 - self.move.post() - assert self.move.state == 'posted' diff --git a/.unported_addons/account_manual_entry_restricted/views/account.xml b/.unported_addons/account_manual_entry_restricted/views/account.xml deleted file mode 100644 index 6e1980e1..00000000 --- a/.unported_addons/account_manual_entry_restricted/views/account.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Account Form: add Entry Restriction - account.account - - - - - - - - - diff --git a/.unported_addons/account_payment_from_move_line/README.rst b/.unported_addons/account_payment_from_move_line/README.rst deleted file mode 100644 index 071b1c1c..00000000 --- a/.unported_addons/account_payment_from_move_line/README.rst +++ /dev/null @@ -1,96 +0,0 @@ -Account Payment From Move Line -============================== -This modules allows to generate a payment from an existing journal item (account.move.line). - -.. contents:: Table of Contents - -Context -------- -In vanilla Odoo, a payment can be registered directly from an invoice. - -.. image:: static/description/invoice_payment_wizard.png - -This allows to automatically fill the payment values based on the invoice. - -However, a journal entry can be created manually to recognize a receivable item. - -.. image:: static/description/receivable_item_list.png - -In such case, prefilling a payment from the receivable item is not possible (in vanilla Odoo). - -Usage ------ -As member of the group ``Accounting / Billing``, I go to the list view of journal items. - -I filter to display the receivable items for a given customer. - -.. image:: static/description/receivable_item_list.png - -I select the items and click on ``Register a payment``. - -.. image:: static/description/receivable_item_list_register_payment.png - -A wizard is opened. - -.. image:: static/description/payment_from_move_line_wizard.png - -I notice that: - -* The payment is prefilled with the sum of amounts from the selected receivables. -* The date of payment is ``Today`` (by default). -* The payment journal is not filled (a default value can be parametrized per company). - -Then, I replace the prefilled amount with a partial payment amount and select a journal. - -The system asks what to do with the balance; either ``Keep Open`` or ``Mark as Fully Paid``. - -.. image:: static/description/wizard_partial_amount.png - -I select ``Mark as Fully Paid`` and select a ``Difference Account``. - -.. image:: static/description/wizard_difference_account.png - -I click on ``Validate``. - -.. image:: static/description/wizard_validate_button.png - -The form view of the new payment is open. - -.. image:: static/description/payment_form.png - -I notice that the selected receivable items are now reconciled. - -.. image:: static/description/journal_items_reconciled.png - -Constraints ------------ -The journal items selected for registering payments must comply with the following constraints. -If one constraint fails, a detailled error message will be displayed. - -Same Currency, Account and Partner -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Selected items must have the same currency, GL account and commercial partner. -This is required so that the payment can be reconciled with the selected journal items. - -Unreconciled -~~~~~~~~~~~~ -Selected items must not be fully reconciled. - -Posted -~~~~~~ -Selected items must be posted. - -Known Issues ------------- -For now, this module does not support payable journal items and outbound payments. -It only supports receivables and inbound payments. - -The reason is that supporting payables and outbound payments adds extra complexity. -This complexity is not required by Numigi's clients. - -A constraint is implemented to prevent users from selecting non-receivable journal items -for registering payments. - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/account_payment_from_move_line/__init__.py b/.unported_addons/account_payment_from_move_line/__init__.py deleted file mode 100644 index 4c6365d4..00000000 --- a/.unported_addons/account_payment_from_move_line/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models, wizard diff --git a/.unported_addons/account_payment_from_move_line/__manifest__.py b/.unported_addons/account_payment_from_move_line/__manifest__.py deleted file mode 100644 index 35de5d85..00000000 --- a/.unported_addons/account_payment_from_move_line/__manifest__.py +++ /dev/null @@ -1,21 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Account Payment From Move Line', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Generate payment from receivable journal item', - 'depends': [ - 'account', - ], - 'data': [ - 'views/account_move_line.xml', - 'wizard/account_payment_from_move_line.xml', - ], - 'installable': True, -} diff --git a/.unported_addons/account_payment_from_move_line/i18n/fr.po b/.unported_addons/account_payment_from_move_line/i18n/fr.po deleted file mode 100644 index 2478f342..00000000 --- a/.unported_addons/account_payment_from_move_line/i18n/fr.po +++ /dev/null @@ -1,271 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * account_payment_from_move_line -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-08 18:42+0000\n" -"PO-Revision-Date: 2019-10-08 14:42-0400\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" -"X-Generator: Poedit 2.0.6\n" - -#. module: account_payment_from_move_line -#: model_terms:ir.ui.view,arch_db:account_payment_from_move_line.account_payment_from_move_line_form -msgid "Cancel" -msgstr "Annuler" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__company_currency_id -msgid "Company Currency" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__counterpart_account_id -msgid "Counterpart Account" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__create_uid -msgid "Created by" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__create_date -msgid "Created on" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__currency_id -msgid "Currency" -msgstr "Devise" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__writeoff_account_id -msgid "Difference Account" -msgstr "Compte de différence" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__display_name -msgid "Display Name" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__id -msgid "ID" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model,name:account_payment_from_move_line.model_account_move_line -msgid "Journal Item" -msgstr "" - -#. module: account_payment_from_move_line -#: selection:account.payment.from.move.line,payment_difference_handling:0 -msgid "Keep open" -msgstr "Laisser ouvert" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line____last_update -msgid "Last Modified on" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__write_uid -msgid "Last Updated by" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__write_date -msgid "Last Updated on" -msgstr "" - -#. module: account_payment_from_move_line -#: selection:account.payment.from.move.line,payment_difference_handling:0 -msgid "Mark as fully paid" -msgstr "Solder la balance" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__communication -msgid "Memo" -msgstr "Mémo" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__move_line_ids -msgid "Move Lines" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__move_lines_currency_id -msgid "Move Lines Currency" -msgstr "" - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:17 -#, python-format -msgid "" -"Only journal items with a receivable account can be selected to register a " -"payment." -msgstr "" -"Seules les écritures ayant un compte recevable peuvent être sélectionnées " -"pour enregistrer un paiement." - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:25 -#, python-format -msgid "Only posted journal items can be selected to register a payment." -msgstr "" -"Seules les écritures comptabilisées peuvent être sélectionnées pour " -"enregistrer un paiement." - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__partner_id -msgid "Partner" -msgstr "Partenaire" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__amount -msgid "Payment Amount" -msgstr "Montant du paiement" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__payment_date -msgid "Payment Date" -msgstr "Date de paiement" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__payment_difference -msgid "Payment Difference" -msgstr "Différence de paiement" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__payment_difference_handling -msgid "Payment Difference Handling" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__writeoff_label -msgid "Payment Difference Label" -msgstr "" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__journal_id -msgid "Payment Journal" -msgstr "Journal de paiement" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__payment_method_id -msgid "Payment Method" -msgstr "Méthode de paiement" - -#. module: account_payment_from_move_line -#: model:ir.model,name:account_payment_from_move_line.model_account_payment_from_move_line -msgid "Payment from Move Line Wizard" -msgstr "Wizard de paiement depuis ligne d'écriture" - -#. module: account_payment_from_move_line -#: model:ir.model,name:account_payment_from_move_line.model_account_payment -msgid "Payments" -msgstr "Paiements" - -#. module: account_payment_from_move_line -#: model_terms:ir.ui.view,arch_db:account_payment_from_move_line.account_payment_from_move_line_form -msgid "Post Difference In" -msgstr "Comptabiliser la différence dans" - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:129 -#: model:ir.actions.server,name:account_payment_from_move_line.action_open_payment_wizard -#: model_terms:ir.ui.view,arch_db:account_payment_from_move_line.account_payment_from_move_line_form -#, python-format -msgid "Register Payment" -msgstr "Enregistrer un paiement" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,field_description:account_payment_from_move_line.field_account_payment_from_move_line__move_lines_residual_amount -msgid "Residual Amount" -msgstr "Montant résiduel" - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:10 -#, python-format -msgid "The journal item has no partner." -msgstr "L'écriture n'a aucun partenaire." - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:33 -#, python-format -msgid "The journal item is already reconciled." -msgstr "L'écriture est déjà réconciliée." - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:45 -#, python-format -msgid "" -"The journal item {item} can not be selected to register a payment.\n" -"{error}" -msgstr "" -"L'écriture {item} ne peut pas être sélectionnée pour enregistrer un " -"paiement.\n" -"{error}" - -#. module: account_payment_from_move_line -#: model:ir.model.fields,help:account_payment_from_move_line.field_account_payment_from_move_line__writeoff_label -msgid "The label of the counterpart that will hold the payment difference." -msgstr "" - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:54 -#, python-format -msgid "" -"The selected journal items are bound to multiple commercial partners:\n" -"\t * {partners}\n" -"A payment can only be registered for a single commercial partner." -msgstr "" -"Les écritures sélectionnées sont liées à plusieurs partenaires " -"commerciaux:\n" -"\t * {partners}\n" -"Un paiement ne peut être enregistrer que pour un seul partenaire commercial." - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:66 -#, python-format -msgid "" -"The selected journal items are bound to multiple journal accounts:\n" -"\t * {accounts}\n" -"A payment can only be registered for a single account." -msgstr "" -"Les écritures sélectionnées sont liées à plusieurs comptes de grand livre:\n" -"\t * {accounts}\n" -"Un paiement ne peut être enregistrer que pour un seul compte." - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:83 -#, python-format -msgid "" -"The selected journal items are in multiple currencies:\n" -"\t * {currencies}\n" -"A payment can only be registered for a single account." -msgstr "" -"Les écritures sélectionnées sont en différentes devises:\n" -"\t * {accounts}\n" -"Un paiement ne peut être enregistrer que pour une seule devise." - -#. module: account_payment_from_move_line -#: model_terms:ir.ui.view,arch_db:account_payment_from_move_line.account_payment_from_move_line_form -msgid "Validate" -msgstr "Valider" - -#. module: account_payment_from_move_line -#: code:addons/account_payment_from_move_line/models/account_move_line.py:94 -#, python-format -msgid "You must select at least one journal item to generate payments." -msgstr "" -"Vous devez sélectionner au moins une écriture pour générer un paiement." diff --git a/.unported_addons/account_payment_from_move_line/models/__init__.py b/.unported_addons/account_payment_from_move_line/models/__init__.py deleted file mode 100644 index 91ee3d59..00000000 --- a/.unported_addons/account_payment_from_move_line/models/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import ( - account_move_line, - account_payment, -) diff --git a/.unported_addons/account_payment_from_move_line/models/account_move_line.py b/.unported_addons/account_payment_from_move_line/models/account_move_line.py deleted file mode 100644 index 961af51d..00000000 --- a/.unported_addons/account_payment_from_move_line/models/account_move_line.py +++ /dev/null @@ -1,130 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import models, _ -from odoo.exceptions import UserError - - -def _check_has_partner(line: 'account.move.line', context: dict): - if not line.partner_id: - raise UserError(_( - 'The journal item has no partner.' - )) - - -def _check_has_receivable_account(line: 'account.move.line', context: dict): - if line.account_id.internal_type != 'receivable': - raise UserError(_( - 'Only journal items with a receivable account ' - 'can be selected to register a payment.' - )) - - -def _check_is_posted(line: 'account.move.line', context: dict): - if line.move_id.state != 'posted': - raise UserError(_( - 'Only posted journal items ' - 'can be selected to register a payment.' - )) - - -def _check_is_not_reconciled(line: 'account.move.line', context: dict): - if line.full_reconcile_id: - raise UserError(_( - 'The journal item is already reconciled.' - )) - - -def _check_single_line_is_selectable(line: 'account.move.line', context: dict): - try: - _check_has_receivable_account(line, context) - _check_is_posted(line, context) - _check_is_not_reconciled(line, context) - _check_has_partner(line, context) - except UserError as err: - raise UserError(_( - 'The journal item {item} can not be selected to register a payment.\n' - '{error}' - ).format(item=line.display_name, error=err.name)) - - -def _check_lines_have_common_commercial_partner(lines: 'account.move.line', context: dict): - partners = lines.mapped('partner_id.commercial_partner_id') - if len(partners) > 1: - raise UserError(_( - 'The selected journal items are bound to multiple commercial partners:' - '\n' - '\t * {partners}' - '\n' - 'A payment can only be registered for a single commercial partner.' - ).format(partners='\n\t * '.join(partners.mapped('display_name')))) - - -def _check_lines_have_common_account(lines: 'account.move.line', context: dict): - accounts = lines.mapped('account_id') - if len(accounts) > 1: - raise UserError(_( - 'The selected journal items are bound to multiple journal accounts:' - '\n' - '\t * {accounts}' - '\n' - 'A payment can only be registered for a single account.' - ).format(accounts='\n\t * '.join(accounts.mapped('display_name')))) - - -def _check_lines_have_common_currency(lines: 'account.move.line', context: dict): - currencies = lines.mapped('currency_id') - - lines_without_currency = lines.filtered(lambda l: not l.currency_id) - if lines_without_currency: - currencies |= lines_without_currency.mapped('company_id.currency_id') - - if len(currencies) > 1: - raise UserError(_( - 'The selected journal items are in multiple currencies:' - '\n' - '\t * {currencies}' - '\n' - 'A payment can only be registered for a single account.' - ).format(currencies='\n\t * '.join(currencies.mapped('display_name')))) - - -def _check_at_least_one_line_selected(lines: 'account.move.line', context: dict): - if not lines: - raise UserError(_( - 'You must select at least one journal item to generate payments.' - )) - - -def _check_lines_are_selectable(lines: 'account.move.line', context: dict): - user_errors = [] - for line in lines: - try: - _check_single_line_is_selectable(line, context) - except UserError as err: - user_errors.append(err) - - if user_errors: - raise UserError('\n\n'.join([e.name for e in user_errors])) - - -class AccountMoveLine(models.Model): - - _inherit = 'account.move.line' - - def open_payment_from_move_line_wizard(self): - _check_at_least_one_line_selected(self, self._context) - _check_lines_have_common_commercial_partner(self, self._context) - _check_lines_have_common_account(self, self._context) - _check_lines_have_common_currency(self, self._context) - _check_lines_are_selectable(self, self._context) - - wizard = self.env['account.payment.from.move.line'].create({}) - wizard.move_line_ids = self - wizard.compute_amount_and_currency() - wizard.compute_communication() - - action = wizard.get_formview_action() - action['target'] = 'new' - action['name'] = _('Register Payment') - return action diff --git a/.unported_addons/account_payment_from_move_line/models/account_payment.py b/.unported_addons/account_payment_from_move_line/models/account_payment.py deleted file mode 100644 index a2289272..00000000 --- a/.unported_addons/account_payment_from_move_line/models/account_payment.py +++ /dev/null @@ -1,30 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, models - - -class AccountPayment(models.Model): - - _inherit = 'account.payment' - - @api.one - @api.depends('invoice_ids', 'payment_type', 'partner_type', 'partner_id') - def _compute_destination_account_id(self): - """Allow to make the destination (counterpart) account explicit. - - In vanilla implementations of payments, the counterpart account is - deduced from either the invoices to pay or the partner selected on the payment. - - In the case of this module, when opening the wizard, we already know - against which counterpart account the payment must registered. - This is the account of the selected journal items (account.move.line). - - Therefore, when posting the payment from the new wizard, the counterpart account - is forced to the expected value. - """ - forced_account_id = self._context.get('force_payment_destination_account_id') - if forced_account_id: - self.destination_account_id = self.env['account.account'].browse(forced_account_id) - else: - super()._compute_destination_account_id() diff --git a/.unported_addons/account_payment_from_move_line/static/description/icon.png b/.unported_addons/account_payment_from_move_line/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/invoice_payment_wizard.png b/.unported_addons/account_payment_from_move_line/static/description/invoice_payment_wizard.png deleted file mode 100644 index a46182ae..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/invoice_payment_wizard.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/journal_items_reconciled.png b/.unported_addons/account_payment_from_move_line/static/description/journal_items_reconciled.png deleted file mode 100644 index 99171b09..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/journal_items_reconciled.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/payment_form.png b/.unported_addons/account_payment_from_move_line/static/description/payment_form.png deleted file mode 100644 index 54b40eb5..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/payment_form.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/payment_from_move_line_wizard.png b/.unported_addons/account_payment_from_move_line/static/description/payment_from_move_line_wizard.png deleted file mode 100644 index 17bff3ed..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/payment_from_move_line_wizard.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list.png b/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list.png deleted file mode 100644 index b191c0a0..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list_register_payment.png b/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list_register_payment.png deleted file mode 100644 index d70ef02f..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/receivable_item_list_register_payment.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/wizard_difference_account.png b/.unported_addons/account_payment_from_move_line/static/description/wizard_difference_account.png deleted file mode 100644 index d6e8e7ba..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/wizard_difference_account.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/wizard_partial_amount.png b/.unported_addons/account_payment_from_move_line/static/description/wizard_partial_amount.png deleted file mode 100644 index 615916a0..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/wizard_partial_amount.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/static/description/wizard_validate_button.png b/.unported_addons/account_payment_from_move_line/static/description/wizard_validate_button.png deleted file mode 100644 index 8330aa85..00000000 Binary files a/.unported_addons/account_payment_from_move_line/static/description/wizard_validate_button.png and /dev/null differ diff --git a/.unported_addons/account_payment_from_move_line/tests/__init__.py b/.unported_addons/account_payment_from_move_line/tests/__init__.py deleted file mode 100644 index 6ef2df91..00000000 --- a/.unported_addons/account_payment_from_move_line/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/account_payment_from_move_line/tests/test_payment_wizard.py b/.unported_addons/account_payment_from_move_line/tests/test_payment_wizard.py deleted file mode 100644 index 1d5cc520..00000000 --- a/.unported_addons/account_payment_from_move_line/tests/test_payment_wizard.py +++ /dev/null @@ -1,334 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -import pytest -from ddt import ddt, data -from odoo.exceptions import UserError -from odoo.tests.common import SavepointCase - - -class PaymentWizardCase(SavepointCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.user = cls.env['res.users'].create({ - 'name': 'My Employee', - 'login': 'employee@example.com', - 'email': 'employee@example.com', - 'groups_id': [ - (5, 0), - (4, cls.env.ref('base.group_user').id), - ], - }) - - cls.payment_journal = cls.env['account.journal'].create({ - 'name': 'My Bank Account', - 'code': 'BNK1', - 'type': 'bank', - }) - - cls.customer_a = cls.env['res.partner'].create({ - 'name': 'Customer A', - 'customer': True, - 'is_company': True, - }) - - cls.contact_a1 = cls.env['res.partner'].create({ - 'name': 'Contact A1', - 'customer': True, - 'parent_id': cls.customer_a.id, - 'type': 'contact', - }) - - cls.contact_a2 = cls.env['res.partner'].create({ - 'name': 'Contact A2', - 'customer': True, - 'parent_id': cls.customer_a.id, - 'type': 'contact', - }) - - cls.customer_b = cls.env['res.partner'].create({ - 'name': 'Customer B', - 'customer': True, - 'is_company': True, - }) - - cls.payment_method = cls.env.ref('account.account_payment_method_manual_in') - cls.sale_journal = cls.env['account.journal'].search([('type', '=', 'sale')], limit=1) - cls.receivable_account = cls.env['account.account'].create({ - 'name': 'Receivable', - 'code': '111211', - 'user_type_id': cls.env.ref('account.data_account_type_receivable').id, - 'reconcile': True, - }) - cls.revenue_account = cls.env['account.account'].create({ - 'name': 'Revenue', - 'code': '444144', - 'user_type_id': cls.env.ref('account.data_account_type_revenue').id, - }) - cls.writeoff_account = cls.env['account.account'].create({ - 'name': 'Write-Off', - 'code': '511555', - 'user_type_id': cls.env.ref('account.data_account_type_expenses').id, - }) - cls.payable_account = cls.env['account.account'].create({ - 'name': 'Payable', - 'code': '222222', - 'user_type_id': cls.env.ref('account.data_account_type_payable').id, - 'reconcile': True, - }) - - @classmethod - def _generate_receivable( - cls, amount, amount_currency=None, currency=None, account=None, - partner=None, no_partner=False - ): - receivable_account = account or cls.receivable_account - partner = partner or cls.customer_a - move = cls.env['account.move'].create({ - 'journal_id': cls.sale_journal.id, - 'line_ids': [ - (0, 0, { - 'partner_id': None if no_partner else partner.id, - 'account_id': receivable_account.id, - 'name': '/', - 'debit': amount if amount > 0 else 0, - 'credit': -amount if amount < 0 else 0, - 'amount_currency': amount_currency, - 'currency_id': currency.id if currency else None, - }), - (0, 0, { - 'account_id': cls.revenue_account.id, - 'name': '/', - 'debit': -amount if amount < 0 else 0, - 'credit': amount if amount > 0 else 0, - }) - ] - }) - move.post() - return move.line_ids.filtered(lambda l: l.account_id == receivable_account) - - def _open_wizard(self, move_lines): - action = move_lines.open_payment_from_move_line_wizard() - return self.env['account.payment.from.move.line'].browse(action['res_id']) - - def _validate_wizard(self, wizard): - wizard.journal_id = self.payment_journal - wizard.payment_method_id = self.payment_method - action = wizard.validate() - return self.env['account.payment'].browse(action['res_id']) - - @staticmethod - def _is_reconciled(move_line): - return bool(move_line.full_reconcile_id) - - -@ddt -class TestPaymentWizard(PaymentWizardCase): - - def test_if_payment_amount_is_sum_of_debits(self): - move_1 = self._generate_receivable(100) - move_2 = self._generate_receivable(200) - wizard = self._open_wizard(move_1 | move_2) - assert wizard.amount == 300 - - def test_if_credit_in_receivable_move_lines__credit_amount_deduced(self): - move_1 = self._generate_receivable(100) - move_2 = self._generate_receivable(-25) - wizard = self._open_wizard(move_1 | move_2) - assert wizard.amount == 75 - - @data('base.CAD', 'base.EUR') - def test_if_receivable_in_foreign_currency__payment_in_foreign_currency(self, currency_ref): - currency = self.env.ref(currency_ref) - move_1 = self._generate_receivable(100, amount_currency=150, currency=currency) - move_2 = self._generate_receivable(200, amount_currency=250, currency=currency) - wizard = self._open_wizard(move_1 | move_2) - assert wizard.amount == 400 - assert wizard.currency_id == currency - - @data('base.CAD', 'base.EUR') - def test_if_credit_receivable_in_foreign_currency__credit_amount_deduced(self, currency_ref): - currency = self.env.ref(currency_ref) - move_1 = self._generate_receivable(100, amount_currency=150, currency=currency) - move_2 = self._generate_receivable(-20, amount_currency=-25, currency=currency) - wizard = self._open_wizard(move_1 | move_2) - assert wizard.amount == 125 - assert wizard.currency_id == currency - - def test_payment_difference_with_debits_in_company_currency(self): - move_1 = self._generate_receivable(100) - move_2 = self._generate_receivable(200) - wizard = self._open_wizard(move_1 | move_2) - wizard.amount = 175 - assert wizard.payment_difference == 125 - - @data('base.CAD', 'base.EUR') - def test_payment_difference_in_foreign_currency(self, currency_ref): - currency = self.env.ref(currency_ref) - move_1 = self._generate_receivable(100, amount_currency=150, currency=currency) - move_2 = self._generate_receivable(200, amount_currency=250, currency=currency) - wizard = self._open_wizard(move_1 | move_2) - wizard.amount = 175 - assert wizard.payment_difference == 225 - - def test_after_validate__payment_is_reconciled(self): - receivable = self._generate_receivable(100) - wizard = self._open_wizard(receivable) - self._validate_wizard(wizard) - assert self._is_reconciled(receivable) - - def test_after_validate__if_open_difference__payment_is_not_reconciled(self): - receivable = self._generate_receivable(100) - wizard = self._open_wizard(receivable) - wizard.amount = 75 - wizard.payment_difference_handling = 'open' - self._validate_wizard(wizard) - assert not self._is_reconciled(receivable) - - def test_after_validate__if_reconcile_difference__payment_is_not_reconciled(self): - receivable = self._generate_receivable(100) - wizard = self._open_wizard(receivable) - wizard.amount = 75 - wizard.payment_difference_handling = 'reconcile' - wizard.writeoff_account_id = self.writeoff_account - self._validate_wizard(wizard) - assert self._is_reconciled(receivable) - - -class TestSelectableMoveLineConstraints(PaymentWizardCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.receivable_1 = cls._generate_receivable(100) - cls.receivable_2 = cls._generate_receivable(200) - - def test_if_no_line_selected__raise_error(self): - with pytest.raises(UserError): - self._open_wizard(self.env['account.move.line']) - - def test_if_not_posted__raise_error(self): - self.sale_journal.update_posted = True - self.receivable_1.move_id.button_cancel() - - with pytest.raises(UserError): - self._open_wizard(self.receivable_1) - - def test_if_not_receivable_account__raise_error(self): - payable = self._generate_receivable(100, account=self.payable_account) - - with pytest.raises(UserError): - self._open_wizard(payable) - - def test_if_no_partner__raise_error(self): - receivable_1 = self._generate_receivable(100, no_partner=True) - - with pytest.raises(UserError): - self._open_wizard(receivable_1) - - def test_if_reconciled__raise_error(self): - wizard = self._open_wizard(self.receivable_1) - self._validate_wizard(wizard) - assert self._is_reconciled(self.receivable_1) - - with pytest.raises(UserError): - self._open_wizard(self.receivable_1 | self.receivable_2) - - def test_if_different_partners__raise_error(self): - receivable_1 = self._generate_receivable(100, partner=self.customer_a) - receivable_2 = self._generate_receivable(200, partner=self.customer_b) - - with pytest.raises(UserError): - self._open_wizard(receivable_1 | receivable_2) - - def test_if_same_commercial_partner__payment_can_be_generated(self): - receivable_1 = self._generate_receivable(100, partner=self.customer_a) - receivable_2 = self._generate_receivable(200, partner=self.contact_a1) - receivable_3 = self._generate_receivable(300, partner=self.contact_a2) - - receivables = receivable_1 | receivable_2 | receivable_3 - - wizard = self._open_wizard(receivables) - self._validate_wizard(wizard) - - for item in receivables: - assert self._is_reconciled(item) - - def test_if_different_accounts__raise_error(self): - account_2 = self.receivable_account.copy({'code': '111212'}) - receivable_1 = self._generate_receivable(100, account=self.receivable_account) - receivable_2 = self._generate_receivable(200, account=account_2) - - with pytest.raises(UserError): - self._open_wizard(receivable_1 | receivable_2) - - def test_if_different_currencies_accounts__raise_error(self): - receivable_1 = self._generate_receivable(100) - receivable_2 = self._generate_receivable(200, currency=self.env.ref('base.CAD')) - - with pytest.raises(UserError): - self._open_wizard(receivable_1 | receivable_2) - - def test_multiple_lines_with_validation_errors(self): - payable_1 = self._generate_receivable(100, account=self.payable_account) - payable_2 = self._generate_receivable(200, account=self.payable_account) - - with pytest.raises(UserError): - self._open_wizard(payable_1 | payable_2) - - -class TestPaymentInDifferentCurrency(PaymentWizardCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.cad = cls.env.ref('base.CAD') - cls.eur = cls.env.ref('base.EUR') - - cls.env['res.currency.rate'].search([]).unlink() - cls._add_currency_rate(cls.cad, 2) - cls._add_currency_rate(cls.eur, 3) - - cls.revenue_account.currency_id = cls.cad - cls.payment_journal.currency_id = cls.eur - - @classmethod - def _add_currency_rate(cls, currency, rate): - cls.env['res.currency.rate'].create({ - 'currency_id': currency.id, - 'rate': rate, - }) - - def test_payment_difference_with_payment_in_different_currency(self): - move_1 = self._generate_receivable(100, amount_currency=200, currency=self.cad) - move_2 = self._generate_receivable(200, amount_currency=600, currency=self.cad) - - wizard = self._open_wizard(move_1 | move_2) - wizard.amount = 100 - wizard.currency_id = self.eur - assert wizard.payment_difference == 1100 # (200 + 600) * 3 / 2 - 100 - - def test_reconcile_difference_with_payment_in_different_currency(self): - receivable = self._generate_receivable(300, amount_currency=600, currency=self.cad) - - wizard = self._open_wizard(receivable) - wizard.amount = 100 - wizard.currency_id = self.eur - wizard.payment_difference_handling = 'reconcile' - wizard.writeoff_account_id = self.writeoff_account - - self._validate_wizard(wizard) - assert self._is_reconciled(receivable) - - def test_open_difference_with_payment_in_different_currency(self): - receivable = self._generate_receivable(300, amount_currency=600, currency=self.cad) - - wizard = self._open_wizard(receivable) - wizard.amount = 150 - wizard.currency_id = self.eur - - self._validate_wizard(wizard) - assert receivable.amount_residual == 250 # 300 - (150 / 3) - assert receivable.amount_residual_currency == 500 # 600 - (150 * 2 / 3) diff --git a/.unported_addons/account_payment_from_move_line/views/account_move_line.xml b/.unported_addons/account_payment_from_move_line/views/account_move_line.xml deleted file mode 100644 index fc337ac4..00000000 --- a/.unported_addons/account_payment_from_move_line/views/account_move_line.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Register Payment - - - ir.actions.server - code - -action = records.open_payment_from_move_line_wizard() - - - - diff --git a/.unported_addons/account_payment_from_move_line/wizard/__init__.py b/.unported_addons/account_payment_from_move_line/wizard/__init__.py deleted file mode 100644 index 358b1b43..00000000 --- a/.unported_addons/account_payment_from_move_line/wizard/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import account_payment_from_move_line diff --git a/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.py b/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.py deleted file mode 100644 index b836e94c..00000000 --- a/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.py +++ /dev/null @@ -1,182 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, fields, models - - -class PaymentFromMoveLineWizard(models.TransientModel): - - _name = 'account.payment.from.move.line' - _description = "Payment from Move Line Wizard" - - move_line_ids = fields.Many2many( - 'account.move.line', - 'account_payment_from_move_line_rel', - 'wizard_id', - 'move_line_id', - string='Move Lines', - ) - - partner_id = fields.Many2one( - 'res.partner', - 'Partner', - compute='_compute_partner', - ) - - @api.depends('move_line_ids') - def _compute_partner(self): - for wizard in self: - wizard.partner_id = wizard.move_line_ids.mapped( - 'partner_id.commercial_partner_id', - ) - - counterpart_account_id = fields.Many2one( - 'account.account', - 'Counterpart Account', - compute='_compute_receivable_account', - ) - - @api.depends('move_line_ids') - def _compute_receivable_account(self): - for wizard in self: - wizard.counterpart_account_id = wizard.move_line_ids.mapped('account_id') - - company_currency_id = fields.Many2one( - 'res.currency', - compute='_compute_currencies', - ) - - move_lines_currency_id = fields.Many2one( - 'res.currency', - compute='_compute_currencies', - ) - - @api.depends('move_line_ids') - def _compute_currencies(self): - for wizard in self: - wizard.company_currency_id = wizard.move_line_ids.mapped('company_id.currency_id') - wizard.move_lines_currency_id = ( - wizard.move_line_ids.mapped('currency_id') or - wizard.company_currency_id - ) - - amount = fields.Monetary('Payment Amount') - - move_lines_residual_amount = fields.Monetary( - 'Residual Amount', - currency_field='move_lines_currency_id', - compute='_compute_move_lines_residual_amount' - ) - - @api.depends('move_lines_currency_id', 'company_currency_id', 'move_line_ids') - def _compute_move_lines_residual_amount(self): - for wizard in self: - if wizard.move_lines_currency_id == wizard.company_currency_id: - wizard.move_lines_residual_amount = sum( - l.amount_residual for l in wizard.move_line_ids - ) - else: - wizard.move_lines_residual_amount = sum( - l.amount_residual_currency for l in wizard.move_line_ids - ) - - currency_id = fields.Many2one('res.currency', 'Currency') - journal_id = fields.Many2one( - 'account.journal', string='Payment Journal', - domain=[('type', 'in', ('bank', 'cash'))], - ) - payment_method_id = fields.Many2one('account.payment.method', 'Payment Method') - communication = fields.Char('Memo') - payment_date = fields.Date(string='Payment Date', default=fields.Date.context_today) - - payment_difference = fields.Monetary(compute='_compute_payment_difference') - payment_difference_handling = fields.Selection([ - ('open', 'Keep open'), - ('reconcile', 'Mark as fully paid'), - ], default='open') - writeoff_account_id = fields.Many2one( - 'account.account', string="Difference Account", - domain=[('deprecated', '=', False)] - ) - writeoff_label = fields.Char( - string='Payment Difference Label', - help='The label of the counterpart that will hold the payment difference.', - default='Write-Off' - ) - - def _get_available_payment_methods(self): - return self.journal_id.inbound_payment_method_ids - - @api.onchange('journal_id') - def _onchange_journal_set_available_payment_methods(self): - available_methods = self._get_available_payment_methods() - self.payment_method_id = available_methods and available_methods[0] or False - return { - 'domain': {'payment_method_id': [('id', 'in', available_methods.ids)]} - } - - @api.depends('move_line_ids', 'amount', 'payment_date', 'currency_id') - def _compute_payment_difference(self): - wizards_with_move_lines = self.filtered(lambda w: w.move_line_ids) - - for wizard in wizards_with_move_lines: - residual_amount = wizard.move_lines_residual_amount - residual_amount_currency = wizard.move_lines_currency_id - payment_currency = wizard.currency_id - company = wizard.move_line_ids.mapped('company_id') - residual_amount_in_payment_currency = residual_amount_currency._convert( - residual_amount, payment_currency, company, - wizard.payment_date or fields.Date.today() - ) - wizard.payment_difference = residual_amount_in_payment_currency - wizard.amount - - def compute_amount_and_currency(self): - """Compute the amount and currency for the wizard. - - The computation of these fields must be triggered manually, - so that the user may override these values. - """ - self.amount = self.move_lines_residual_amount - self.currency_id = self.move_lines_currency_id - - def compute_communication(self): - lines_with_reference = self.move_line_ids.filtered(lambda l: l.ref) - self.communication = ' '.join(sorted(lines_with_reference.mapped('ref'))) - - def _get_payment_vals(self): - return { - 'amount': self.amount, - 'currency_id': self.currency_id.id, - 'journal_id': self.journal_id.id, - 'partner_id': self.partner_id.id, - 'partner_type': 'customer', - 'payment_method_id': self.payment_method_id.id, - 'payment_type': 'inbound', - 'communication': self.communication, - 'payment_date': self.payment_date, - } - - def _get_payment_post_context(self): - return { - 'force_payment_destination_account_id': self.counterpart_account_id.id, - } - - def _reconcile_payment(self, payment): - payment_move_line = payment.move_line_ids.filtered( - lambda l: l.account_id == self.counterpart_account_id - ) - lines_to_reconcile = (self.move_line_ids | payment_move_line) - - if self.payment_difference and self.payment_difference_handling == 'reconcile': - lines_to_reconcile.reconcile( - writeoff_acc_id=self.writeoff_account_id, - writeoff_journal_id=self.journal_id, - ) - else: - lines_to_reconcile.reconcile() - - def validate(self): - payment = self.env['account.payment'].create(self._get_payment_vals()) - payment.with_context(**self._get_payment_post_context()).post() - self._reconcile_payment(payment) - return payment.get_formview_action() diff --git a/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.xml b/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.xml deleted file mode 100644 index 2cab76f6..00000000 --- a/.unported_addons/account_payment_from_move_line/wizard/account_payment_from_move_line.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Payment From Move Line Wizard - account.payment.from.move.line - -
- - - - - - - - - - - - - - - - - -
-
-
- -
diff --git a/.unported_addons/account_report_line_menu/README.rst b/.unported_addons/account_report_line_menu/README.rst deleted file mode 100644 index ded231a0..00000000 --- a/.unported_addons/account_report_line_menu/README.rst +++ /dev/null @@ -1,11 +0,0 @@ -Account Report Line Menu -======================== -This module adds a menu entry to configure the report lines of HTML accounting reports (Balance Sheet, Income Statement, etc). - -.. image:: static/description/menu.png - -.. image:: static/description/report_line_list.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/account_report_line_menu/__init__.py b/.unported_addons/account_report_line_menu/__init__.py deleted file mode 100644 index d2ac44f2..00000000 --- a/.unported_addons/account_report_line_menu/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/account_report_line_menu/__manifest__.py b/.unported_addons/account_report_line_menu/__manifest__.py deleted file mode 100644 index 88e7ee1f..00000000 --- a/.unported_addons/account_report_line_menu/__manifest__.py +++ /dev/null @@ -1,20 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Account Report Line Menu', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Add menu entry to configure accounting report lines', - 'depends': [ - 'account_reports', - ], - 'data': [ - 'menu.xml', - ], - 'installable': True, -} diff --git a/.unported_addons/account_report_line_menu/i18n/fr.po b/.unported_addons/account_report_line_menu/i18n/fr.po deleted file mode 100644 index 75cd1eb7..00000000 --- a/.unported_addons/account_report_line_menu/i18n/fr.po +++ /dev/null @@ -1,22 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * account_report_line_menu -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-13 19:15+0000\n" -"PO-Revision-Date: 2019-05-13 19:15+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: account_report_line_menu -#: model:ir.actions.act_window,name:account_report_line_menu.report_line_action -#: model:ir.ui.menu,name:account_report_line_menu.report_line_menu -msgid "Financial Report Lines" -msgstr "Lignes de rapports financiers" diff --git a/.unported_addons/account_report_line_menu/menu.xml b/.unported_addons/account_report_line_menu/menu.xml deleted file mode 100644 index 0e9488b6..00000000 --- a/.unported_addons/account_report_line_menu/menu.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - diff --git a/.unported_addons/account_report_line_menu/static/description/icon.png b/.unported_addons/account_report_line_menu/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/account_report_line_menu/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/account_report_line_menu/static/description/menu.png b/.unported_addons/account_report_line_menu/static/description/menu.png deleted file mode 100644 index 2da56e1e..00000000 Binary files a/.unported_addons/account_report_line_menu/static/description/menu.png and /dev/null differ diff --git a/.unported_addons/account_report_line_menu/static/description/report_line_list.png b/.unported_addons/account_report_line_menu/static/description/report_line_list.png deleted file mode 100644 index 9c4e1f45..00000000 Binary files a/.unported_addons/account_report_line_menu/static/description/report_line_list.png and /dev/null differ diff --git a/.unported_addons/analytic_source/README.rst b/.unported_addons/analytic_source/README.rst deleted file mode 100644 index 2af85fa6..00000000 --- a/.unported_addons/analytic_source/README.rst +++ /dev/null @@ -1,14 +0,0 @@ -=============== -Analytic Source -=============== - -Add a field source on account.analytic.line. - -When an invoice is opened, all analytic lines generated will have this invoice as origin. - -This module is intended to be inherited in order to add multiple types of source -for an analytic line. - -Contributors ------------- -* David Dufresne (david.dufresne@numigi.com) diff --git a/.unported_addons/analytic_source/__init__.py b/.unported_addons/analytic_source/__init__.py deleted file mode 100644 index fc8d60fb..00000000 --- a/.unported_addons/analytic_source/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/analytic_source/__manifest__.py b/.unported_addons/analytic_source/__manifest__.py deleted file mode 100644 index 4e26d798..00000000 --- a/.unported_addons/analytic_source/__manifest__.py +++ /dev/null @@ -1,22 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Analytic Source', - 'version': '1.0.0', - 'author': 'Savoir-faire Linux', - 'maintainer': 'Numigi', - 'website': 'http://www.savoirfairelinux.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Add field source to analytic lines.', - 'depends': [ - 'account', - ], - 'data': [ - 'views/account_analytic_line.xml', - ], - 'installable': True, - 'application': False, -} diff --git a/.unported_addons/analytic_source/i18n/fr.po b/.unported_addons/analytic_source/i18n/fr.po deleted file mode 100644 index d50cbb09..00000000 --- a/.unported_addons/analytic_source/i18n/fr.po +++ /dev/null @@ -1,29 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * analytic_source -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 10.0e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-11-22 13:33-0500\n" -"PO-Revision-Date: 2017-11-22 13:38-0500\n" -"Last-Translator: David Dufresne \n" -"Language-Team: \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" -"X-Generator: Poedit 1.8.7.1\n" - -#. module: analytic_source -#: model:ir.model.fields,field_description:analytic_source.field_account_analytic_line_source -msgid "Source" -msgstr "Source" - -#. module: analytic_source -#: selection:account.analytic.line,source:0 -#: model:ir.model.fields,field_description:analytic_source.field_account_analytic_line_invoice_id -msgid "Invoice" -msgstr "Facture" diff --git a/.unported_addons/analytic_source/models/__init__.py b/.unported_addons/analytic_source/models/__init__.py deleted file mode 100644 index 6b891568..00000000 --- a/.unported_addons/analytic_source/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import ( - account_analytic_line, - account_invoice, -) diff --git a/.unported_addons/analytic_source/models/account_analytic_line.py b/.unported_addons/analytic_source/models/account_analytic_line.py deleted file mode 100644 index 31362328..00000000 --- a/.unported_addons/analytic_source/models/account_analytic_line.py +++ /dev/null @@ -1,14 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import fields, models - - -class AccountAnalyticLine(models.Model): - - _inherit = 'account.analytic.line' - - source = fields.Reference(selection=[ - ('account.invoice', 'Invoice'), - ], readonly=True, string="Source") diff --git a/.unported_addons/analytic_source/models/account_invoice.py b/.unported_addons/analytic_source/models/account_invoice.py deleted file mode 100644 index 15a7821b..00000000 --- a/.unported_addons/analytic_source/models/account_invoice.py +++ /dev/null @@ -1,17 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, models - - -class AccountInvoice(models.Model): - - _inherit = 'account.invoice' - - def action_invoice_open(self): - super(AccountInvoice, self).action_invoice_open() - - for invoice in self: - lines = invoice.mapped('move_id.line_ids.analytic_line_ids') - lines.write({'source': 'account.invoice,%s' % invoice.id}) diff --git a/.unported_addons/analytic_source/views/account_analytic_line.xml b/.unported_addons/analytic_source/views/account_analytic_line.xml deleted file mode 100644 index 0e06c577..00000000 --- a/.unported_addons/analytic_source/views/account_analytic_line.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - account.analytic.line.form - account.analytic.line - - - - - - - - - - diff --git a/.unported_addons/budget_analysis_account_move_line/README.rst b/.unported_addons/budget_analysis_account_move_line/README.rst deleted file mode 100644 index fb4640e9..00000000 --- a/.unported_addons/budget_analysis_account_move_line/README.rst +++ /dev/null @@ -1,23 +0,0 @@ -Budget Analysis Account Move Lines -================================== -This module allows to open the list of journal entries from a budget line. - -Usage ------ -As member of the group ``Accounting & Finance / Accountant``, I go to ``Accounting / Reporting / Budget Analysis``. - -.. image:: static/description/budget_analysis_menu.png - -I notice that the amounts in the column ``Practical Amount`` are clickable. - -.. image:: static/description/budget_line_list.png - -If I click on one of these amounts, the list of journal items related to this budget line is displayed. - -.. image:: static/description/budget_line_click.png - -.. image:: static/description/journal_item_list.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/budget_analysis_account_move_line/__init__.py b/.unported_addons/budget_analysis_account_move_line/__init__.py deleted file mode 100644 index 21228467..00000000 --- a/.unported_addons/budget_analysis_account_move_line/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/budget_analysis_account_move_line/__manifest__.py b/.unported_addons/budget_analysis_account_move_line/__manifest__.py deleted file mode 100644 index e3a5e7cb..00000000 --- a/.unported_addons/budget_analysis_account_move_line/__manifest__.py +++ /dev/null @@ -1,19 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Budget Analysis Account Move Lines', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Display the journal entries from the budget analysis report.', - 'depends': ['account_budget'], - 'data': [ - 'views/assets.xml', - 'views/crossovered_budget_lines.xml', - ], - 'installable': True, -} diff --git a/.unported_addons/budget_analysis_account_move_line/i18n/fr.po b/.unported_addons/budget_analysis_account_move_line/i18n/fr.po deleted file mode 100644 index 1e99e38f..00000000 --- a/.unported_addons/budget_analysis_account_move_line/i18n/fr.po +++ /dev/null @@ -1,26 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * budget_analysis_account_move_line -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-19 01:59+0000\n" -"PO-Revision-Date: 2019-06-19 01:59+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: budget_analysis_account_move_line -#: model:ir.model,name:budget_analysis_account_move_line.model_crossovered_budget_lines -msgid "Budget Line" -msgstr "" - -#. module: budget_analysis_account_move_line -#: model:ir.actions.act_window,name:budget_analysis_account_move_line.action_move_lines_from_budget_lines -msgid "Journal Items" -msgstr "Écritures comptables" diff --git a/.unported_addons/budget_analysis_account_move_line/models/__init__.py b/.unported_addons/budget_analysis_account_move_line/models/__init__.py deleted file mode 100644 index 639ad51b..00000000 --- a/.unported_addons/budget_analysis_account_move_line/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import crossovered_budget_lines diff --git a/.unported_addons/budget_analysis_account_move_line/models/crossovered_budget_lines.py b/.unported_addons/budget_analysis_account_move_line/models/crossovered_budget_lines.py deleted file mode 100644 index 49e524d0..00000000 --- a/.unported_addons/budget_analysis_account_move_line/models/crossovered_budget_lines.py +++ /dev/null @@ -1,32 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import models - - -class BudgetLine(models.Model): - - _inherit = 'crossovered.budget.lines' - - def _get_move_line_domain(self): - """Get the domain to filter the list view of journal items.""" - domain = [ - ('date', '>=', self.date_from), - ('date', '<=', self.date_to), - ] - - if self.general_budget_id: - domain.append(('account_id', 'in', self.general_budget_id.account_ids.ids)) - - if self.analytic_account_id: - domain.append(('analytic_account_id', '=', self.analytic_account_id.id)) - - return domain - - def action_view_move_lines(self): - action = self.env.ref( - 'budget_analysis_account_move_line.action_move_lines_from_budget_lines') - result = action.read()[0] - result['display_name'] = '{} ({})'.format(result['name'], self.display_name) - result['domain'] = self._get_move_line_domain() - return result diff --git a/.unported_addons/budget_analysis_account_move_line/static/description/budget_analysis_menu.png b/.unported_addons/budget_analysis_account_move_line/static/description/budget_analysis_menu.png deleted file mode 100644 index 30979878..00000000 Binary files a/.unported_addons/budget_analysis_account_move_line/static/description/budget_analysis_menu.png and /dev/null differ diff --git a/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_click.png b/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_click.png deleted file mode 100644 index 43cbec9a..00000000 Binary files a/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_click.png and /dev/null differ diff --git a/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_list.png b/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_list.png deleted file mode 100644 index 3a9c246d..00000000 Binary files a/.unported_addons/budget_analysis_account_move_line/static/description/budget_line_list.png and /dev/null differ diff --git a/.unported_addons/budget_analysis_account_move_line/static/description/icon.png b/.unported_addons/budget_analysis_account_move_line/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/budget_analysis_account_move_line/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/budget_analysis_account_move_line/static/description/journal_item_list.png b/.unported_addons/budget_analysis_account_move_line/static/description/journal_item_list.png deleted file mode 100644 index aad4cacc..00000000 Binary files a/.unported_addons/budget_analysis_account_move_line/static/description/journal_item_list.png and /dev/null differ diff --git a/.unported_addons/budget_analysis_account_move_line/static/src/js/widget.js b/.unported_addons/budget_analysis_account_move_line/static/src/js/widget.js deleted file mode 100644 index ad4e2d9b..00000000 --- a/.unported_addons/budget_analysis_account_move_line/static/src/js/widget.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) - License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL.html). -*/ -odoo.define("budget_analysis_account_move_line.link_widget", function(require) { -"use strict"; - -var rpc = require("web.rpc"); -var basicFields = require("web.basic_fields"); -var AbstractField = require("web.AbstractField"); - -var BudgetAnalysisToMoveLines = basicFields.FieldFloat.extend({ - className: "o_field_float o_field_number o_budget_analysis_to_move_lines", - tagName: "a", - events: _.extend({}, AbstractField.prototype.events, { - "click": "_onClick", - }), - /** - * When clicking on the amount, trigger the action to display the list of move lines. - */ - async _onClick(event){ - event.preventDefault(); - event.stopPropagation(); - var action = await rpc.query({ - model: "crossovered.budget.lines", - method: "action_view_move_lines", - args: [this.record.res_id], - context: this.getSession().user_context, - }); - this.do_action(action); - }, - /** - * Display the field as a clickable link. - * - * Because of bootstrap, nodes without href do not appear as clickable links. - */ - _render(){ - this._super.apply(this, arguments); - this.$el.attr("href", "#"); - }, - /** - * Fix the non-break spaces in amounts. - * - * When using an node instead of a span, the non-break spaces - * after or behind the currency symbol is displayed as " ". - * - * This function replaces the " " with a real non-break space caracter. - */ - _formatValue(value){ - var formattedValue = this._super.apply(this, arguments); - return formattedValue.replace(" ", " "); - }, -}); - -var registry = require("web.field_registry"); -registry.add("budget_analysis_to_move_lines", BudgetAnalysisToMoveLines); - -}); diff --git a/.unported_addons/budget_analysis_account_move_line/tests/__init__.py b/.unported_addons/budget_analysis_account_move_line/tests/__init__.py deleted file mode 100644 index d2ac44f2..00000000 --- a/.unported_addons/budget_analysis_account_move_line/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/budget_analysis_account_move_line/tests/test_crossovered_budget_lines.py b/.unported_addons/budget_analysis_account_move_line/tests/test_crossovered_budget_lines.py deleted file mode 100644 index 12157fc9..00000000 --- a/.unported_addons/budget_analysis_account_move_line/tests/test_crossovered_budget_lines.py +++ /dev/null @@ -1,61 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from datetime import datetime, timedelta -from odoo.tests import common - - -class TestGetMoveLineDomain(common.SavepointCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.date_from = datetime.now() - cls.date_to = datetime.now() + timedelta(365) - cls.budget_1 = cls.env['crossovered.budget'].create({ - 'name': 'Budget Test 1', - 'date_from': cls.date_from, - 'date_to': cls.date_to, - }) - - cls.analytic_account = cls.env['account.analytic.account'].create({ - 'name': 'Analytic Account 1' - }) - - cls.account = cls.env['account.account'].create({ - 'name': 'General Expenses', - 'code': '510100', - 'user_type_id': cls.env.ref('account.data_account_type_expenses').id, - }) - - cls.budget_position = cls.env['account.budget.post'].create({ - 'name': 'General Expenses', - 'account_ids': [(4, cls.account.id)], - }) - - cls.budget_line_1 = cls.env['crossovered.budget.lines'].create({ - 'crossovered_budget_id': cls.budget_1.id, - 'analytic_account_id': cls.analytic_account.id, - 'general_budget_id': cls.budget_position.id, - 'planned_amount': 1000, - 'date_from': cls.budget_1.date_from, - 'date_to': cls.budget_1.date_to, - }) - - def _get_move_line_domain(self): - return self.budget_line_1.action_view_move_lines()['domain'] - - def test_move_date_between_budget_boundaries(self): - domain = self._get_move_line_domain() - assert ('date', '>=', self.budget_1.date_from) in domain - assert ('date', '<=', self.budget_1.date_to) in domain - - def test_if_budget_line_has_budget_position__general_account_filtered(self): - self.budget_line_1.general_budget_id = self.budget_position - domain = self._get_move_line_domain() - assert ('account_id', 'in', [self.account.id]) in domain - - def test_if_budget_line_has_analytic_account__analytic_account_filtered(self): - self.budget_line_1.analytic_account_id = self.analytic_account - domain = self._get_move_line_domain() - assert ('analytic_account_id', '=', self.analytic_account.id) in domain diff --git a/.unported_addons/budget_analysis_account_move_line/views/assets.xml b/.unported_addons/budget_analysis_account_move_line/views/assets.xml deleted file mode 100644 index d6d4f33b..00000000 --- a/.unported_addons/budget_analysis_account_move_line/views/assets.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/.unported_addons/budget_analysis_account_move_line/views/crossovered_budget_lines.xml b/.unported_addons/budget_analysis_account_move_line/views/crossovered_budget_lines.xml deleted file mode 100644 index 7911e37d..00000000 --- a/.unported_addons/budget_analysis_account_move_line/views/crossovered_budget_lines.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Journal Items - ir.actions.act_window - account.move.line - list,pivot,graph,form - - - - Budget Line Form: make practical amount clickable to view journal items - crossovered.budget.lines - - - - budget_analysis_to_move_lines - - - - - - Budget Line List: make practical amount clickable to view journal items - crossovered.budget.lines - - - - budget_analysis_to_move_lines - - - - - diff --git a/.unported_addons/invoice_write_access/README.rst b/.unported_addons/invoice_write_access/README.rst deleted file mode 100644 index 833331f0..00000000 --- a/.unported_addons/invoice_write_access/README.rst +++ /dev/null @@ -1,37 +0,0 @@ -Invoice Write Access -==================== -This module restricts the access to update/create/delete an invoice to a specific group. - -Context -------- -In vanilla Odoo, any member of ``Sale / User`` or ``Purchase / User`` is allowed to update/create/delete an invoice. - -How The Module Works --------------------- -A new technical group ``Invoice Write Access`` is added. - -.. image:: static/description/invoice_group.png - -The group ``Accounting / Billing`` inherits this group. -It is not possible to have ``Accounting / Billing`` without ``Invoice Write Access``. - -Hidden Buttons -~~~~~~~~~~~~~~ -The buttons to create an invoice are hidden on the purchase and sales order for non-members of -the group ``Invoice Write Access``. See modules ``invoice_write_access_sale`` and ``invoice_write_access_sale``. - -Extended Security Rules -~~~~~~~~~~~~~~~~~~~~~~~ -The module `base_extended_security `_ -is used to prevent non-members of the new group to create/update/delete an invoice. - -This mecanism prevents user to create an invoice through the web interface, but does not impact -the internal behavior of Odoo. This limits the risk to create side effects related to modifying native Odoo ACL. - -For example, if an unauthorized user attemps to create an invoice, the following message will be displayed: - -.. image:: static/description/invoice_create_message.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/invoice_write_access/__init__.py b/.unported_addons/invoice_write_access/__init__.py deleted file mode 100644 index 6da4fa4e..00000000 --- a/.unported_addons/invoice_write_access/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/invoice_write_access/__manifest__.py b/.unported_addons/invoice_write_access/__manifest__.py deleted file mode 100644 index 8b4d8c92..00000000 --- a/.unported_addons/invoice_write_access/__manifest__.py +++ /dev/null @@ -1,21 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Invoice Write Access', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Restrict the creation/update of invoices', - 'depends': [ - 'account', - 'base_extended_security', - ], - 'data': [ - 'security/res_groups.xml', - ], - 'installable': True, -} diff --git a/.unported_addons/invoice_write_access/i18n/fr.po b/.unported_addons/invoice_write_access/i18n/fr.po deleted file mode 100644 index 51eb299c..00000000 --- a/.unported_addons/invoice_write_access/i18n/fr.po +++ /dev/null @@ -1,44 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * invoice_write_access -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-20 19:15+0000\n" -"PO-Revision-Date: 2019-08-20 19:15+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: invoice_write_access -#: model:ir.model,name:invoice_write_access.model_account_invoice -msgid "Invoice" -msgstr "" - -#. module: invoice_write_access -#: model:res.groups,name:invoice_write_access.group_invoice -msgid "Invoice Write Access" -msgstr "Accès modification de facture" - -#. module: invoice_write_access -#: code:addons/invoice_write_access/models/invoice.py:7 -#, python-format -msgid "You are not authorized to create an invoice." -msgstr "Vous n'êtes pas autorisé à créer une facture." - -#. module: invoice_write_access -#: code:addons/invoice_write_access/models/invoice.py:15 -#, python-format -msgid "You are not authorized to delete an invoice." -msgstr "Vous n'êtes pas autorisé à supprimer une facture." - -#. module: invoice_write_access -#: code:addons/invoice_write_access/models/invoice.py:11 -#, python-format -msgid "You are not authorized to update an invoice." -msgstr "Vous n'êtes pas autorisé à modifier une facture." diff --git a/.unported_addons/invoice_write_access/models/__init__.py b/.unported_addons/invoice_write_access/models/__init__.py deleted file mode 100644 index ecfe5c8a..00000000 --- a/.unported_addons/invoice_write_access/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import invoice diff --git a/.unported_addons/invoice_write_access/models/invoice.py b/.unported_addons/invoice_write_access/models/invoice.py deleted file mode 100644 index 6e02bd9c..00000000 --- a/.unported_addons/invoice_write_access/models/invoice.py +++ /dev/null @@ -1,37 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import models, _ -from odoo.exceptions import AccessError - -INVOICE_CREATE_ERROR_MESSAGE = _( - "You are not authorized to create an invoice." -) - -INVOICE_WRITE_ERROR_MESSAGE = _( - "You are not authorized to update an invoice." -) - -INVOICE_UNLINK_ERROR_MESSAGE = _( - "You are not authorized to delete an invoice." -) - - -class Invoice(models.Model): - - _inherit = 'account.invoice' - - def check_extended_security_write(self): - super().check_extended_security_write() - if not self.env.user.has_group('invoice_write_access.group_invoice'): - raise AccessError(_(INVOICE_WRITE_ERROR_MESSAGE)) - - def check_extended_security_create(self): - super().check_extended_security_create() - if not self.env.user.has_group('invoice_write_access.group_invoice'): - raise AccessError(_(INVOICE_CREATE_ERROR_MESSAGE)) - - def check_extended_security_unlink(self): - super().check_extended_security_unlink() - if not self.env.user.has_group('invoice_write_access.group_invoice'): - raise AccessError(_(INVOICE_UNLINK_ERROR_MESSAGE)) diff --git a/.unported_addons/invoice_write_access/security/res_groups.xml b/.unported_addons/invoice_write_access/security/res_groups.xml deleted file mode 100644 index ce50b619..00000000 --- a/.unported_addons/invoice_write_access/security/res_groups.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Invoice Write Access - - - - - - - diff --git a/.unported_addons/invoice_write_access/static/description/icon.png b/.unported_addons/invoice_write_access/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/invoice_write_access/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access/static/description/invoice_create_message.png b/.unported_addons/invoice_write_access/static/description/invoice_create_message.png deleted file mode 100644 index f6684caf..00000000 Binary files a/.unported_addons/invoice_write_access/static/description/invoice_create_message.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access/static/description/invoice_group.png b/.unported_addons/invoice_write_access/static/description/invoice_group.png deleted file mode 100644 index bd44250b..00000000 Binary files a/.unported_addons/invoice_write_access/static/description/invoice_group.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access/tests/__init__.py b/.unported_addons/invoice_write_access/tests/__init__.py deleted file mode 100644 index 6ef2df91..00000000 --- a/.unported_addons/invoice_write_access/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/invoice_write_access/tests/test_invoice_access.py b/.unported_addons/invoice_write_access/tests/test_invoice_access.py deleted file mode 100644 index fcdc695b..00000000 --- a/.unported_addons/invoice_write_access/tests/test_invoice_access.py +++ /dev/null @@ -1,46 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -import pytest -from odoo.exceptions import AccessError -from odoo.tests.common import SavepointCase - - -class TestInvoiceAccess(SavepointCase): - - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.user = cls.env['res.users'].create({ - 'name': 'My User', - 'login': 'testinvoice@example.com', - 'email': 'testinvoice@example.com', - 'groups_id': [ - (4, cls.env.ref('purchase.group_purchase_user').id), - (4, cls.env.ref('sales_team.group_sale_salesman').id), - ], - }) - - def test_if_user_unauthorized__on_create__raise_error(self): - with pytest.raises(AccessError): - self.env['account.invoice'].sudo(self.user).check_extended_security_create() - - def test_if_user_authorized__on_create__error_not_raised(self): - self.user.groups_id |= self.env.ref('invoice_write_access.group_invoice') - self.env['account.invoice'].sudo(self.user).check_extended_security_create() - - def test_if_user_unauthorized__on_write__raise_error(self): - with pytest.raises(AccessError): - self.env['account.invoice'].sudo(self.user).check_extended_security_write() - - def test_if_user_authorized__on_write__error_not_raised(self): - self.user.groups_id |= self.env.ref('invoice_write_access.group_invoice') - self.env['account.invoice'].sudo(self.user).check_extended_security_write() - - def test_if_user_unauthorized__on_unlink__raise_error(self): - with pytest.raises(AccessError): - self.env['account.invoice'].sudo(self.user).check_extended_security_unlink() - - def test_if_user_authorized__on_unlink__error_not_raised(self): - self.user.groups_id |= self.env.ref('invoice_write_access.group_invoice') - self.env['account.invoice'].sudo(self.user).check_extended_security_unlink() diff --git a/.unported_addons/invoice_write_access_purchase/README.rst b/.unported_addons/invoice_write_access_purchase/README.rst deleted file mode 100644 index d4f7fe1b..00000000 --- a/.unported_addons/invoice_write_access_purchase/README.rst +++ /dev/null @@ -1,11 +0,0 @@ -Invoice Write Access - Purchase -=============================== -This module is a binding between the modules ``invoice_write_access`` and ``purchase``. - -On the form view of a purchase order, the button to create an invoice is hidden for non-members of the group ``Invoice Write Access``. - -.. image:: static/description/purchase_order_form.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/invoice_write_access_purchase/__init__.py b/.unported_addons/invoice_write_access_purchase/__init__.py deleted file mode 100644 index 6ef2df91..00000000 --- a/.unported_addons/invoice_write_access_purchase/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/invoice_write_access_purchase/__manifest__.py b/.unported_addons/invoice_write_access_purchase/__manifest__.py deleted file mode 100644 index e15aefdc..00000000 --- a/.unported_addons/invoice_write_access_purchase/__manifest__.py +++ /dev/null @@ -1,22 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Invoice Write Access / Purchase', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Restrict the creation/update of vendor bills', - 'depends': [ - 'invoice_write_access', - 'purchase', - ], - 'data': [ - 'views/purchase_order.xml', - ], - 'installable': True, - 'auto_install': True, -} diff --git a/.unported_addons/invoice_write_access_purchase/static/description/icon.png b/.unported_addons/invoice_write_access_purchase/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/invoice_write_access_purchase/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access_purchase/static/description/purchase_order_form.png b/.unported_addons/invoice_write_access_purchase/static/description/purchase_order_form.png deleted file mode 100644 index 5cc3d5ed..00000000 Binary files a/.unported_addons/invoice_write_access_purchase/static/description/purchase_order_form.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access_purchase/views/purchase_order.xml b/.unported_addons/invoice_write_access_purchase/views/purchase_order.xml deleted file mode 100644 index 5881fee1..00000000 --- a/.unported_addons/invoice_write_access_purchase/views/purchase_order.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Purchase Order: restrict button to create invoice - purchase.order - - - - invoice_write_access.group_invoice - - - invoice_write_access.group_invoice - - - - - diff --git a/.unported_addons/invoice_write_access_sale/README.rst b/.unported_addons/invoice_write_access_sale/README.rst deleted file mode 100644 index 422a2d57..00000000 --- a/.unported_addons/invoice_write_access_sale/README.rst +++ /dev/null @@ -1,11 +0,0 @@ -Invoice Write Access - Sale -=========================== -This module is a binding between the modules ``invoice_write_access`` and ``sale``. - -On the form view of a sale order, the button to create an invoice is hidden for non-members of the group ``Invoice Write Access``. - -.. image:: static/description/sale_order_form.png - -Contributors ------------- -* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/.unported_addons/invoice_write_access_sale/__init__.py b/.unported_addons/invoice_write_access_sale/__init__.py deleted file mode 100644 index 6ef2df91..00000000 --- a/.unported_addons/invoice_write_access_sale/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). diff --git a/.unported_addons/invoice_write_access_sale/__manifest__.py b/.unported_addons/invoice_write_access_sale/__manifest__.py deleted file mode 100644 index 1444b9b2..00000000 --- a/.unported_addons/invoice_write_access_sale/__manifest__.py +++ /dev/null @@ -1,22 +0,0 @@ -# © 2019 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Invoice Write Access / Sale', - 'version': '1.0.0', - 'author': 'Numigi', - 'maintainer': 'Numigi', - 'website': 'https://www.numigi.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Restrict the creation/update of customer invoices', - 'depends': [ - 'invoice_write_access', - 'sale_management', - ], - 'data': [ - 'views/sale_order.xml', - ], - 'installable': True, - 'auto_install': True, -} diff --git a/.unported_addons/invoice_write_access_sale/static/description/icon.png b/.unported_addons/invoice_write_access_sale/static/description/icon.png deleted file mode 100644 index 92a86b10..00000000 Binary files a/.unported_addons/invoice_write_access_sale/static/description/icon.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access_sale/static/description/sale_order_form.png b/.unported_addons/invoice_write_access_sale/static/description/sale_order_form.png deleted file mode 100644 index a8f8dded..00000000 Binary files a/.unported_addons/invoice_write_access_sale/static/description/sale_order_form.png and /dev/null differ diff --git a/.unported_addons/invoice_write_access_sale/views/sale_order.xml b/.unported_addons/invoice_write_access_sale/views/sale_order.xml deleted file mode 100644 index c0cfa8db..00000000 --- a/.unported_addons/invoice_write_access_sale/views/sale_order.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Sale Order: restrict button to create invoice - sale.order - - - - invoice_write_access.group_invoice - - - invoice_write_access.group_invoice - - - - - - - - - diff --git a/.unported_addons/payment_workflow/README.rst b/.unported_addons/payment_workflow/README.rst deleted file mode 100644 index 07d59d47..00000000 --- a/.unported_addons/payment_workflow/README.rst +++ /dev/null @@ -1,17 +0,0 @@ -================ -Payment Workflow -================ - -This module improves payment management in Odoo with a workflow more similar to invoices. - -It adds : -* 2 new contact type: Customer Payment and Supplier Payment -* a chatter below the payment form view - -It also adds a method that allows to get a partner child that corresponds to the first existant -address in a list given in parameter, if no child is found, the parent himself is returned - -Contributors ------------- -* David Dufresne (david.dufresne@numigi.com) -* Yasmine El Mrini (yasmine.elmrini@numigi.com) diff --git a/.unported_addons/payment_workflow/__init__.py b/.unported_addons/payment_workflow/__init__.py deleted file mode 100644 index fc8d60fb..00000000 --- a/.unported_addons/payment_workflow/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/payment_workflow/__manifest__.py b/.unported_addons/payment_workflow/__manifest__.py deleted file mode 100644 index e96ea681..00000000 --- a/.unported_addons/payment_workflow/__manifest__.py +++ /dev/null @@ -1,23 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Payment Workflow', - 'version': '1.0.0', - 'author': 'Savoir-faire Linux', - 'maintainer': 'Numigi', - 'website': 'http://www.savoirfairelinux.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Add new contact types.', - 'depends': [ - 'base', - 'account', - ], - 'data': [ - 'views/account_payment.xml', - ], - 'installable': False, - 'application': False, -} diff --git a/.unported_addons/payment_workflow/i18n/fr.po b/.unported_addons/payment_workflow/i18n/fr.po deleted file mode 100644 index 903d4d65..00000000 --- a/.unported_addons/payment_workflow/i18n/fr.po +++ /dev/null @@ -1,31 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * payment_workflow -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 10.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-11-17 03:35+0000\n" -"PO-Revision-Date: 2017-11-17 03:35+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: payment_workflow -#: model:ir.model,name:payment_workflow.model_res_partner -msgid "Partner" -msgstr "Partenaire" - -#. module: payment_workflow -#: selection:res.partner,type:0 -msgid "Supplier Payment" -msgstr "Paiement fournisseur" - -#. module: payment_workflow -#: selection:res.partner,type:0 -msgid "Customer Payment" -msgstr "Paiement client" diff --git a/.unported_addons/payment_workflow/models/__init__.py b/.unported_addons/payment_workflow/models/__init__.py deleted file mode 100644 index 79a1f43f..00000000 --- a/.unported_addons/payment_workflow/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import ( - account_payment, - res_partner, -) diff --git a/.unported_addons/payment_workflow/models/account_payment.py b/.unported_addons/payment_workflow/models/account_payment.py deleted file mode 100644 index 8d52b16a..00000000 --- a/.unported_addons/payment_workflow/models/account_payment.py +++ /dev/null @@ -1,25 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import fields, models - - -class AccountPayment(models.Model): - - _name = 'account.payment' - _inherit = ['mail.thread', 'account.payment'] - - payment_type = fields.Selection(track_visibility='onchange') - payment_method_id = fields.Many2one(track_visibility='onchange') - partner_type = fields.Selection(track_visibility='onchange') - partner_id = fields.Many2one(track_visibility='onchange') - amount = fields.Monetary(track_visibility='onchange') - currency_id = fields.Many2one(track_visibility='onchange') - payment_date = fields.Date(track_visibility='onchange') - communication = fields.Char(track_visibility='onchange') - journal_id = fields.Many2one(track_visibility='onchange') - state = fields.Selection(track_visibility='onchange') - payment_reference = fields.Char(track_visibility='onchange') - check_amount_in_words = fields.Char(track_visibility='onchange') - check_number = fields.Integer(track_visibility='onchange') diff --git a/.unported_addons/payment_workflow/models/res_partner.py b/.unported_addons/payment_workflow/models/res_partner.py deleted file mode 100644 index 212d8f09..00000000 --- a/.unported_addons/payment_workflow/models/res_partner.py +++ /dev/null @@ -1,43 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import fields, models - - -class ResPartner(models.Model): - - _inherit = 'res.partner' - - type = fields.Selection(selection_add=[ - ('supplier_payment', 'Supplier Payment'), - ('customer_payment', 'Customer Payment'), - ]) - - def get_preferred_address(self, contact_types): - """Get a preferred address from a partner. - - This function is meant to be used in a email template. - - For example, in a payment notice email, the field partner_to - could be filled as follow: - - ${object.partner_id.get_preferred_address( - ['supplier_payment', 'invoice']).id|safe} - - If the partner has an address of type 'supplier_payment', - this address will be used in the email. Otherwise, an address - of type 'invoice' will be selected. If the partner does not have - an address of type 'invoice' either, the email will be sent - to the partner himself. - - :param list contact_types: The types of address in order of priority - :rtype: res.partner - :return: The address - """ - for contact_type in contact_types: - contact_id = self.address_get([contact_type])[contact_type] - if contact_id != self.id: - return self.browse(contact_id) - - return self diff --git a/.unported_addons/payment_workflow/tests/__init__.py b/.unported_addons/payment_workflow/tests/__init__.py deleted file mode 100644 index aff185bc..00000000 --- a/.unported_addons/payment_workflow/tests/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import test_res_partner diff --git a/.unported_addons/payment_workflow/tests/test_res_partner.py b/.unported_addons/payment_workflow/tests/test_res_partner.py deleted file mode 100644 index 0576c1de..00000000 --- a/.unported_addons/payment_workflow/tests/test_res_partner.py +++ /dev/null @@ -1,43 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from openerp.tests import SavepointCase - - -class TestResPartner(SavepointCase): - - @classmethod - def setUpClass(cls): - super(TestResPartner, cls).setUpClass() - - cls.parent = cls.env['res.partner'].create({ - 'name': 'Parent', - }) - - cls.invoice_address = cls.env['res.partner'].create({ - 'name': 'Invoice Address', - 'type': 'invoice', - 'parent_id': cls.parent.id, - }) - - cls.customer_payment = cls.env['res.partner'].create({ - 'name': 'Customer Payment', - 'type': 'customer_payment', - 'parent_id': cls.parent.id, - }) - - def test_01_get_preferred_address_first_contact_returned(self): - contact = self.parent.get_preferred_address( - ['customer_payment', 'invoice']) - self.assertEquals(contact, self.customer_payment) - - def test_02_get_preferred_address_second_contact_returned(self): - contact = self.parent.get_preferred_address( - ['supplier_payment', 'invoice']) - self.assertEquals(contact, self.invoice_address) - - def test_03_get_preferred_address_parent_returned(self): - contact = self.parent.get_preferred_address( - ['supplier_payment', 'delivery']) - self.assertEquals(contact, self.parent) diff --git a/.unported_addons/payment_workflow/views/account_payment.xml b/.unported_addons/payment_workflow/views/account_payment.xml deleted file mode 100644 index 0f60d9fe..00000000 --- a/.unported_addons/payment_workflow/views/account_payment.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - account.payment.form - account.payment - - - -
- - -
-
-
-
- -
diff --git a/.unported_addons/payment_workflow_enterprise/README.rst b/.unported_addons/payment_workflow_enterprise/README.rst deleted file mode 100644 index a89c204b..00000000 --- a/.unported_addons/payment_workflow_enterprise/README.rst +++ /dev/null @@ -1,11 +0,0 @@ -=========================== -Payment Workflow Enterprise -=========================== - -This module allows to choose the new contact type Customer Payment if it exists, if it doesn't the invoice address -is chosen, so that the system set the mails receiver that corresponds to payment orders to the person in charge of them. - -Contributors ------------- -* David Dufresne (david.dufresne@numigi.com) -* Yasmine El Mrini (yasmine.elmrini@numigi.com) diff --git a/.unported_addons/payment_workflow_enterprise/__init__.py b/.unported_addons/payment_workflow_enterprise/__init__.py deleted file mode 100644 index fc8d60fb..00000000 --- a/.unported_addons/payment_workflow_enterprise/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import models diff --git a/.unported_addons/payment_workflow_enterprise/__manifest__.py b/.unported_addons/payment_workflow_enterprise/__manifest__.py deleted file mode 100644 index 1bf45d5a..00000000 --- a/.unported_addons/payment_workflow_enterprise/__manifest__.py +++ /dev/null @@ -1,20 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -{ - 'name': 'Payment Workflow Enterprise', - 'version': '1.0.0', - 'author': 'Savoir-faire Linux', - 'maintainer': 'Numigi', - 'website': 'http://www.savoirfairelinux.com', - 'license': 'LGPL-3', - 'category': 'Accounting', - 'summary': 'Set customer payment as default invoice address.', - 'depends': [ - 'payment_workflow', - 'account_reports', - ], - 'installable': False, - 'application': False, -} diff --git a/.unported_addons/payment_workflow_enterprise/models/__init__.py b/.unported_addons/payment_workflow_enterprise/models/__init__.py deleted file mode 100644 index 4f0d71fe..00000000 --- a/.unported_addons/payment_workflow_enterprise/models/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from . import account_report_context_followup diff --git a/.unported_addons/payment_workflow_enterprise/models/account_report_context_followup.py b/.unported_addons/payment_workflow_enterprise/models/account_report_context_followup.py deleted file mode 100644 index 1960d275..00000000 --- a/.unported_addons/payment_workflow_enterprise/models/account_report_context_followup.py +++ /dev/null @@ -1,20 +0,0 @@ -# © 2017 Savoir-faire Linux -# © 2018 Numigi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -from odoo import api, models - - -class AccountReportContextFollowup(models.TransientModel): - - _inherit = 'account.report.context.followup' - - @api.depends('partner_id') - def _get_invoice_address(self): - for partner in self: - if partner.partner_id: - partner.invoice_address_id = ( - partner.partner_id.get_preferred_address( - ['customer_payment', 'invoice'])) - else: - partner.invoice_address_id = False diff --git a/Dockerfile b/Dockerfile index 0175a0eb..51ad7ccf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM quay.io/numigi/odoo-public:14.latest -MAINTAINER numigi +LABEL maintainer="contact@numigi.com" USER root diff --git a/account_additional_group/__manifest__.py b/account_additional_group/__manifest__.py index b72cc00e..fda191c1 100644 --- a/account_additional_group/__manifest__.py +++ b/account_additional_group/__manifest__.py @@ -10,7 +10,9 @@ "license": "LGPL-3", "category": "Accounting", "summary": "Add additional groups of accounts", - "depends": ["account",], + "depends": [ + "account", + ], "data": [ "security/ir.model.access.csv", "views/account_account.xml", diff --git a/account_additional_group/tests/test_account_additional_group.py b/account_additional_group/tests/test_account_additional_group.py index 502b199f..e3daf739 100644 --- a/account_additional_group/tests/test_account_additional_group.py +++ b/account_additional_group/tests/test_account_additional_group.py @@ -1,7 +1,6 @@ # © 2021 - today Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from datetime import datetime, timedelta from odoo.tests import common diff --git a/account_analytic_required_forbidden/i18n/fr.po b/account_analytic_required_forbidden/i18n/fr.po index 880d443c..09377aad 100644 --- a/account_analytic_required_forbidden/i18n/fr.po +++ b/account_analytic_required_forbidden/i18n/fr.po @@ -90,7 +90,8 @@ msgstr "" #, python-format msgid "" "The journal entry can not be posted because the line {line} has no analytic " -"account. The account {account} requires an analytic account." +"account. The account {account} requires " +"an analytic account." msgstr "" "La pièce comptable ne peut pas être validée, car la ligne {line} n’a pas de " "compte analytique. Le compte {account} oblige de renseigner le compte " diff --git a/account_analytic_required_forbidden/models.py b/account_analytic_required_forbidden/models.py index 2966da8d..70db8c1c 100644 --- a/account_analytic_required_forbidden/models.py +++ b/account_analytic_required_forbidden/models.py @@ -38,7 +38,8 @@ def _check_analytic_account_required_or_forbidden(self): raise ValidationError( _( "The journal entry can not be posted because the line {line} " - "has no analytic account. The account {account} requires an analytic account." + "has no analytic account. The account {account} requires " + "an analytic account." ).format( line=_format_account_move_line(self), account=self.account_id.display_name, diff --git a/account_closing_journal/__manifest__.py b/account_closing_journal/__manifest__.py index d8191313..79daa149 100644 --- a/account_closing_journal/__manifest__.py +++ b/account_closing_journal/__manifest__.py @@ -10,7 +10,9 @@ "license": "LGPL-3", "category": "Accounting", "summary": "Allow to define a fiscal year closing journal", - "depends": ["account",], + "depends": [ + "account", + ], "data": [ "views/account_journal.xml", "views/account_move.xml", diff --git a/account_closing_journal_mis_builder/__manifest__.py b/account_closing_journal_mis_builder/__manifest__.py index 8b860e0c..0ab6ed54 100644 --- a/account_closing_journal_mis_builder/__manifest__.py +++ b/account_closing_journal_mis_builder/__manifest__.py @@ -14,7 +14,9 @@ # OCA/mis-builder "mis_builder", ], - "data": ["views/mis_report.xml",], + "data": [ + "views/mis_report.xml", + ], "installable": True, "auto_install": True, } diff --git a/account_closing_wizard/__manifest__.py b/account_closing_wizard/__manifest__.py index de63e595..e68df428 100644 --- a/account_closing_wizard/__manifest__.py +++ b/account_closing_wizard/__manifest__.py @@ -10,7 +10,10 @@ "license": "LGPL-3", "category": "Accounting", "summary": "Add a wizard to close an accounting exercise", - "depends": ["account_closing_journal", "date_range",], + "depends": [ + "account_closing_journal", + "date_range", + ], "data": [ "security/ir.model.access.csv", "views/account_account.xml", diff --git a/account_closing_wizard/wizard/account_closing_wizard.py b/account_closing_wizard/wizard/account_closing_wizard.py index 5a63cab2..26c41554 100644 --- a/account_closing_wizard/wizard/account_closing_wizard.py +++ b/account_closing_wizard/wizard/account_closing_wizard.py @@ -27,9 +27,12 @@ class AccountClosingWizard(models.TransientModel): move_id = fields.Many2one("account.move") def _check_draft_account_move_in_period(self): - domain = [("state", "=", "draft"), ("move_type", "=", "entry"), - ("company_id", "=", self.env.company.id), - ("date", "<=", self.date_to)] + domain = [ + ("state", "=", "draft"), + ("move_type", "=", "entry"), + ("company_id", "=", self.env.company.id), + ("date", "<=", self.date_to), + ] account_ids = self.env["account.move"].search(domain) if account_ids: raise ValidationError( @@ -65,7 +68,7 @@ def _make_account_move(self): income_lines = self._prepare_income_lines() earnings_line = self._prepare_earnings_line() - balance = sum(l["debit"] - l["credit"] for l in income_lines) + balance = sum(line["debit"] - line["credit"] for line in income_lines) earnings_line["debit"] = -balance if balance < 0 else 0 earnings_line["credit"] = balance if balance > 0 else 0 @@ -87,7 +90,8 @@ def _get_account_move_ref(self): date_from = self.date_from.strftime(DATE_FORMAT) date_to = self.date_to.strftime(DATE_FORMAT) return _("Period closing from {date_from} to {date_to}").format( - date_from=date_from, date_to=date_to, + date_from=date_from, + date_to=date_to, ) def _prepare_earnings_line(self): @@ -110,7 +114,9 @@ def _get_earnings_account(self): _( "No account defined under company {company} " "as the default account for retained earnings." - ).format(company=self.company_id.display_name,) + ).format( + company=self.company_id.display_name, + ) ) return account @@ -120,7 +126,7 @@ def _prepare_income_lines(self): self._prepare_income_line(account) for account in self._get_income_accounts() ) - return [l for l in lines if l["debit"] or l["credit"]] + return [line for line in lines if line["debit"] or line["credit"]] def _prepare_income_line(self, account): balance = self._get_account_balance(account) diff --git a/account_fr_ca_labels/models.py b/account_fr_ca_labels/models.py index 18f95a33..fd362d21 100644 --- a/account_fr_ca_labels/models.py +++ b/account_fr_ca_labels/models.py @@ -2,26 +2,26 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import logging -from odoo import api, models +from odoo import models _logger = logging.getLogger(__name__) ENGLISH_CREDIT_NOTE_TERMS = [ - 'credit note', - 'credit notes', - 'Credit Note', - 'Credit Notes', - 'Credit note', - 'Credit notes', - 'refund', - 'Refund', + "credit note", + "credit notes", + "Credit Note", + "Credit Notes", + "Credit note", + "Credit notes", + "refund", + "Refund", ] class IrTranslation(models.Model): - _inherit = 'ir.translation' + _inherit = "ir.translation" def _load_module_terms(self, modules, langs, overwrite=False): result = super()._load_module_terms(modules, langs, overwrite) @@ -36,7 +36,7 @@ def _update_fr_ca_terms(self): def _update_credit_note_translations(env): - u"""Update the term `Avoir` to `Note de crédit`. + """Update the term `Avoir` to `Note de crédit`. The term `Avoir` and all its derivatives (avoir, avoirs, l'avoir, d'avoir) must not always be updated to `Note de crédit`. @@ -52,7 +52,6 @@ def _update_credit_note_translations(env): """ mapping = [ ("Facture de l'avoir", "Note de crédit"), - ("l'avoir", "la note de crédit"), ("L'avoir", "La note de crédit"), ("d'avoirs", "de notes de crédit"), @@ -64,21 +63,24 @@ def _update_credit_note_translations(env): ("le prochain avoir", "la prochaine note de crédit"), ("avoir", "note de crédit"), ("Avoir", "Note de crédit"), - # Grammatical errors ("Note de crédits", "Notes de crédit"), ("note de crédits", "notes de crédit"), ] for source, destination in mapping: translations = _find_translations_term_with_value(env, source) + # Fixing it not using lambda function: + # lambda t: _translation_contains_credit_note(t) + # Use instead _translation_contains_credit_note. It is the same. credit_note_translations = translations.filtered( - lambda t: _translation_contains_credit_note(t)) + _translation_contains_credit_note + ) for translation in credit_note_translations: _replace_term_in_translation(translation, source, destination) def _update_aged_balance_translations(env): - u"""Update the term `Balance âgée` to `Âge des comptes`.""" + """Update the term `Balance âgée` to `Âge des comptes`.""" mapping = [ ("Balance agée des clients", "Âge des comptes clients"), ("Balance agée des fournisseurs", "Âge des comptes fournisseurs"), @@ -90,10 +92,9 @@ def _update_aged_balance_translations(env): def _update_reconciliation_translations(env): - u"""Update the term `Lettrage` to `Conciliation`.""" + """Update the term `Lettrage` to `Conciliation`.""" mapping = [ ("Modèles de lettrage", "Modèles de conciliation bancaire"), - ("de lettrage", "de conciliation"), ("du lettrage", "de la conciliation"), ("le lettrage", "la conciliation"), @@ -101,9 +102,8 @@ def _update_reconciliation_translations(env): ("Lettrer", "Réconcilier"), ("lettrer", "réconcilier"), ("Lettrage", "Conciliation"), - # Grammatical errors - ("annuler le lettrage l'entrée", "annuler la conciliation") + ("annuler le lettrage l'entrée", "annuler la conciliation"), ] _replace_terms(env, mapping) @@ -144,23 +144,25 @@ def _find_translations_term_with_value(env, value): ) AND value like %s """, - ('ir.%', '%{}%'.format(value), ) + ( + "ir.%", + "%{}%".format(value), + ), ) translation_ids = [r[0] for r in env.cr.fetchall()] - return env['ir.translation'].browse(translation_ids) + return env["ir.translation"].browse(translation_ids) def _translation_contains_credit_note(translation): """Evaluate whether the source of the translation contains `credit note`.""" - return any( - source in translation.src - for source in ENGLISH_CREDIT_NOTE_TERMS - ) + return any(source in translation.src for source in ENGLISH_CREDIT_NOTE_TERMS) def _replace_term_in_translation(translation, source, dest): - _logger.info(( - "Replacing the term '{source}' with '{dest}' for the french translation " - "'{value}'." - ).format(source=source, dest=dest, value=translation.value)) + _logger.info( + ( + "Replacing the term '{source}' with '{dest}' for the french translation " + "'{value}'." + ).format(source=source, dest=dest, value=translation.value) + ) translation.value = translation.value.replace(source, dest) diff --git a/account_invoice_constraint_chronology_forced/i18n/fr.po b/account_invoice_constraint_chronology_forced/i18n/fr.po index 156862e4..509461aa 100644 --- a/account_invoice_constraint_chronology_forced/i18n/fr.po +++ b/account_invoice_constraint_chronology_forced/i18n/fr.po @@ -50,8 +50,8 @@ msgstr "" #: code:addons/account_invoice_constraint_chronology_forced/models/account_journal.py:0 #, python-format msgid "" -"You cannot change the Type of the Journal because there is At Least One " -"Account Move linked to the Journal." +"You cannot change the Type of the Journal because there is " +"At Least One Account Move linked to the Journal." msgstr "" "Vous ne pouvez pas modifier le type du journal car au moins " "une pièce comptable est associée au journal." diff --git a/account_invoice_constraint_chronology_forced/models/account_journal.py b/account_invoice_constraint_chronology_forced/models/account_journal.py index 1bda9323..89b0338f 100644 --- a/account_invoice_constraint_chronology_forced/models/account_journal.py +++ b/account_invoice_constraint_chronology_forced/models/account_journal.py @@ -22,8 +22,8 @@ def _onchange_type(self): if moves_count > 0: raise UserError( _( - "You cannot change the Type of the Journal because there is At Least One " - "Account Move linked to the Journal." + "You cannot change the Type of the Journal because there is " + "At Least One Account Move linked to the Journal." ) ) diff --git a/account_move_reversal_access/__manifest__.py b/account_move_reversal_access/__manifest__.py index b3b4ef04..13c04391 100644 --- a/account_move_reversal_access/__manifest__.py +++ b/account_move_reversal_access/__manifest__.py @@ -3,7 +3,10 @@ { "name": "Account Move Reversal Access", - "summary": "Restricting access to the function of reversing Journal Entries and resetting to draft ().", + "summary": """ + Restricting access to the function of reversing Journal + Entries and resetting to draft (). + """, "version": "14.0.2.0.0", "website": "https://bit.ly/numigi-com", "author": "Numigi", diff --git a/account_move_reversed_entry/tests/test_account_move.py b/account_move_reversed_entry/tests/test_account_move.py index 714b7d3c..37c027f5 100644 --- a/account_move_reversed_entry/tests/test_account_move.py +++ b/account_move_reversed_entry/tests/test_account_move.py @@ -2,7 +2,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields -from odoo.exceptions import UserError from odoo.tests import common diff --git a/account_move_unique_reversal/i18n/fr.po b/account_move_unique_reversal/i18n/fr.po index 91b52a2c..8b140fc9 100644 --- a/account_move_unique_reversal/i18n/fr.po +++ b/account_move_unique_reversal/i18n/fr.po @@ -27,7 +27,7 @@ msgid "The accounting entry {} is already reversed (by entry {}). You can only r msgstr "La pièce comptable {} est déjà renversée (pièce {}). Vous ne pouvez renverser une pièce qu’une seule fois." #. module: account_move_unique_reversal -#: code:addons/account_move_unique_reversal/models/account_move_reversal.py:26 +#: code:addons/account_move_unique_reversal/models/account_move_reversal.py:28 #, python-format msgid "The accounting entry {} is the reversal of another entry ({}). You can not reverse a reversal accounting entry." msgstr "La pièce comptable {} est le renversement d’une autre pièce comptable ({}). Vous ne pouvez pas renverser une pièce comptable qui est le renversement d’une autre pièce." diff --git a/account_move_unique_reversal/models/account_move.py b/account_move_unique_reversal/models/account_move.py index 5b79c968..7aa78a19 100644 --- a/account_move_unique_reversal/models/account_move.py +++ b/account_move_unique_reversal/models/account_move.py @@ -1,7 +1,7 @@ # © 2021 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import _, api, fields, models +from odoo import _, models from odoo.exceptions import UserError @@ -11,21 +11,23 @@ class AccountMove(models.Model): def _reverse_moves(self, default_values_list=None, cancel=False): for move in self: if move.reversal_move_id and move.journal_id.type not in ( - 'sale', 'purchase'): + "sale", + "purchase", + ): raise UserError( _( "The accounting entry {} is already reversed (by entry {}). " "You can only reverse an accounting entry once." - ).format(move.display_name, - move.reversal_move_id.display_name) + ).format(move.display_name, move.reversal_move_id.display_name) ) if move.reversed_entry_id and move.journal_id.type not in ( - 'sale', 'purchase'): + "sale", + "purchase", + ): raise UserError( _( "The accounting entry {} is the reversal of another entry " "({}). You can not reverse a reversal accounting entry." - ).format(move.display_name, - move.reversed_entry_id.display_name) + ).format(move.display_name, move.reversed_entry_id.display_name) ) return super()._reverse_moves(default_values_list, cancel) diff --git a/account_negative_debit_credit/tests/test_account_move_line.py b/account_negative_debit_credit/tests/test_account_move_line.py index 95ba8e97..32c16c11 100644 --- a/account_negative_debit_credit/tests/test_account_move_line.py +++ b/account_negative_debit_credit/tests/test_account_move_line.py @@ -44,30 +44,78 @@ def _get_asset_line(self, move): return move.line_ids.filtered(lambda l: l.account_id == self.asset) def test_negative_debit(self): - move = self._create_move([ - (0, 0, {"account_id": self.expense.id, "debit": -10,}), - (0, 0, {"account_id": self.asset.id, "debit": 10,}), - ]) + move = self._create_move( + [ + ( + 0, + 0, + { + "account_id": self.expense.id, + "debit": -10, + }, + ), + ( + 0, + 0, + { + "account_id": self.asset.id, + "debit": 10, + }, + ), + ] + ) line = move.line_ids[0] assert line.debit == 0 assert line.credit == 10 def test_negative_credit(self): - move = self._create_move([ - (0, 0, {"account_id": self.expense.id, "credit": 10,}), - (0, 0, {"account_id": self.asset.id, "credit": -10,}), - ]) + move = self._create_move( + [ + ( + 0, + 0, + { + "account_id": self.expense.id, + "credit": 10, + }, + ), + ( + 0, + 0, + { + "account_id": self.asset.id, + "credit": -10, + }, + ), + ] + ) line = move.line_ids[1] assert line.debit == 10 assert line.credit == 0 def test_negative_debit_and_credit(self): - move = self._create_move([ - (0, 0, {"account_id": self.expense.id, "credit": 10,}), - (0, 0, {"account_id": self.asset.id, "credit": -10,}), - ]) + move = self._create_move( + [ + ( + 0, + 0, + { + "account_id": self.expense.id, + "credit": 10, + }, + ), + ( + 0, + 0, + { + "account_id": self.asset.id, + "credit": -10, + }, + ), + ] + ) expense_line = move.line_ids[0] assert expense_line.debit == 0 @@ -78,10 +126,26 @@ def test_negative_debit_and_credit(self): assert asset_line.credit == 0 def test_write(self): - move = self._create_move([ - (0, 0, {"account_id": self.expense.id, "debit": 10,}), - (0, 0, {"account_id": self.asset.id, "credit": 10,}), - ]) + move = self._create_move( + [ + ( + 0, + 0, + { + "account_id": self.expense.id, + "debit": 10, + }, + ), + ( + 0, + 0, + { + "account_id": self.asset.id, + "credit": 10, + }, + ), + ] + ) move.write( { "line_ids": [ diff --git a/account_payment_cancel_group/__manifest__.py b/account_payment_cancel_group/__manifest__.py index 4fd97246..a3a94bfa 100644 --- a/account_payment_cancel_group/__manifest__.py +++ b/account_payment_cancel_group/__manifest__.py @@ -10,7 +10,12 @@ "license": "LGPL-3", "category": "Accounting", "summary": "Add a user group allowed to cancel payments", - "depends": ["account",], - "data": ["security/res_groups.xml", "views/account_payment.xml",], + "depends": [ + "account", + ], + "data": [ + "security/res_groups.xml", + "views/account_payment.xml", + ], "installable": True, } diff --git a/account_payment_cancel_group/models/account_move.py b/account_payment_cancel_group/models/account_move.py index 069d9d8a..12bda1a0 100644 --- a/account_payment_cancel_group/models/account_move.py +++ b/account_payment_cancel_group/models/account_move.py @@ -1,7 +1,7 @@ # © 2019 Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, models, _ +from odoo import models, _ from odoo.exceptions import AccessError @@ -19,7 +19,9 @@ def button_cancel(self): def _check_payment_cancel_authorization(self): if self._contains_payments() and not self._user_can_cancel_payments(): - raise AccessError(_("You are not authorized to reset to draft or cancel payments.")) + raise AccessError( + _("You are not authorized to reset to draft or cancel payments.") + ) def _user_can_cancel_payments(self): return self.env.user.has_group( diff --git a/account_payment_cancel_group/tests/test_payment_cancel.py b/account_payment_cancel_group/tests/test_payment_cancel.py index 0830c278..6cd02a89 100644 --- a/account_payment_cancel_group/tests/test_payment_cancel.py +++ b/account_payment_cancel_group/tests/test_payment_cancel.py @@ -11,30 +11,38 @@ class TestPaymentCancel(common.SavepointCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.user = cls.env['res.users'].create({ - 'name': 'Test User', - 'email': 'test@test.com', - 'login': 'test@test.com', - 'groups_id': [ - (4, cls.env.ref('account.group_account_manager').id), - ] - }) - - cls.journal = cls.env['account.journal'].create({ - 'name': 'Test Bank Journal', - 'type': 'bank', - 'code': 'TEST', - }) - - cls.supplier = cls.env['res.partner'].create({'name': 'Supplier'}) - cls.payment = cls.env['account.payment'].create({ - 'journal_id': cls.journal.id, - 'partner_id': cls.supplier.id, - 'amount': 100, - 'payment_type': 'outbound', - 'payment_method_id': cls.env.ref('account.account_payment_method_manual_out').id, - 'partner_type': 'supplier', - }) + cls.user = cls.env["res.users"].create( + { + "name": "Test User", + "email": "test@test.com", + "login": "test@test.com", + "groups_id": [ + (4, cls.env.ref("account.group_account_manager").id), + ], + } + ) + + cls.journal = cls.env["account.journal"].create( + { + "name": "Test Bank Journal", + "type": "bank", + "code": "TEST", + } + ) + + cls.supplier = cls.env["res.partner"].create({"name": "Supplier"}) + cls.payment = cls.env["account.payment"].create( + { + "journal_id": cls.journal.id, + "partner_id": cls.supplier.id, + "amount": 100, + "payment_type": "outbound", + "payment_method_id": cls.env.ref( + "account.account_payment_method_manual_out" + ).id, + "partner_type": "supplier", + } + ) def test_if_not_member_of_group__action_draft_not_allowed(self): with pytest.raises(AccessError): @@ -45,11 +53,13 @@ def test_if_not_member_of_group__action_cancel_not_allowed(self): self.payment.sudo(self.user).action_cancel() def test_if_member_of_group__user_allowed(self): - self.user.groups_id |= self.env.ref('account_payment_cancel_group.group_cancel_payments') + self.user.groups_id |= self.env.ref( + "account_payment_cancel_group.group_cancel_payments" + ) self.payment.sudo(self.user).action_draft() - assert self.payment.state == 'draft' + assert self.payment.state == "draft" self.payment.sudo(self.user).action_cancel() - assert self.payment.state == 'cancel' + assert self.payment.state == "cancel" def test_call_method_with_empty_recordset(self): self.env["account.payment"].sudo(self.user).action_draft() diff --git a/account_payment_term_usage/models/__init__.py b/account_payment_term_usage/models/__init__.py index 4f4995b4..856e377e 100644 --- a/account_payment_term_usage/models/__init__.py +++ b/account_payment_term_usage/models/__init__.py @@ -2,6 +2,6 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from . import ( - account_move, + account_move, account_payment_term, ) diff --git a/account_payment_term_usage/models/account_move.py b/account_payment_term_usage/models/account_move.py index e9a5f330..5aaa2631 100644 --- a/account_payment_term_usage/models/account_move.py +++ b/account_payment_term_usage/models/account_move.py @@ -9,7 +9,10 @@ class AccountMove(models.Model): _inherit = "account.move" payment_term_usage = fields.Selection( - [("sale", "Sales"), ("purchase", "Purchases"),], + [ + ("sale", "Sales"), + ("purchase", "Purchases"), + ], compute="_compute_payment_term_usage", ) diff --git a/account_payment_term_usage/tests/test_account_move.py b/account_payment_term_usage/tests/test_account_move.py index bdfa4703..c754f477 100644 --- a/account_payment_term_usage/tests/test_account_move.py +++ b/account_payment_term_usage/tests/test_account_move.py @@ -1,11 +1,8 @@ # © 2021 - today Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -import pytest -from ddt import ddt, data, unpack -from datetime import datetime, timedelta +from ddt import ddt from odoo.tests.common import SavepointCase -from odoo.exceptions import ValidationError @ddt @@ -14,7 +11,11 @@ class TestAccountMove(SavepointCase): def setUpClass(cls): super().setUpClass() cls.journal = cls.env["account.journal"].create( - {"name": "Journal", "type": "purchase", "code": "SAJ",} + { + "name": "Journal", + "type": "purchase", + "code": "SAJ", + } ) cls.partner = cls.env["res.partner"].create({"name": "Partner"}) cls.invoice = cls.env["account.move"].create( diff --git a/account_payment_widget_link/tests/__init__.py b/account_payment_widget_link/tests/__init__.py index b67e645c..d36fa2b3 100644 --- a/account_payment_widget_link/tests/__init__.py +++ b/account_payment_widget_link/tests/__init__.py @@ -2,4 +2,3 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL.html). from . import test_account_move_line - diff --git a/account_report_trial_balance/controller/print_report.py b/account_report_trial_balance/controller/print_report.py index 1ee66f23..0caf702c 100644 --- a/account_report_trial_balance/controller/print_report.py +++ b/account_report_trial_balance/controller/print_report.py @@ -1,22 +1,25 @@ # © 2021 Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -import json from odoo import http from odoo.http import request class PrintGeneralLedger(http.Controller): - @http.route('/web/account_report_trial_balance/', type='http', auth='user') + @http.route( + "/web/account_report_trial_balance/", type="http", auth="user" + ) def account_report_trial_balance_pdf(self, report_id, token): - output_pdf = request.env['account.report.trial.balance'].browse(report_id).get_pdf() + output_pdf = ( + request.env["account.report.trial.balance"].browse(report_id).get_pdf() + ) response = request.make_response( output_pdf, headers=[ - ('Content-Type', 'application/pdf'), - ('Content-Disposition', 'attachment; filename=trial_balance.pdf;') - ] + ("Content-Type", "application/pdf"), + ("Content-Disposition", "attachment; filename=trial_balance.pdf;"), + ], ) - response.set_cookie('fileToken', token) + response.set_cookie("fileToken", token) return response diff --git a/account_type_sane/__manifest__.py b/account_type_sane/__manifest__.py index ef4b1af6..3d809429 100644 --- a/account_type_sane/__manifest__.py +++ b/account_type_sane/__manifest__.py @@ -10,7 +10,9 @@ "license": "LGPL-3", "category": "Accounting", "summary": "Make the account types more user friendly", - "depends": ["account",], + "depends": [ + "account", + ], "data": [ "views/menu.xml", "views/account_account.xml", diff --git a/bank_statement_import_csv/error.py b/bank_statement_import_csv/error.py index 831da773..f229a88b 100644 --- a/bank_statement_import_csv/error.py +++ b/bank_statement_import_csv/error.py @@ -11,6 +11,5 @@ class BankStatementError: kwargs: dict = field(default_factory=lambda: {}) - def is_bank_statement_error(value): return isinstance(value, BankStatementError) diff --git a/bank_statement_import_csv/loader.py b/bank_statement_import_csv/loader.py index ee930984..b9e04a0e 100644 --- a/bank_statement_import_csv/loader.py +++ b/bank_statement_import_csv/loader.py @@ -158,9 +158,9 @@ def _get_currency_amount(self, row): currency_amount = self._get_cell_decimal(row, self._currency_amount_index) if ( - isinstance(amount, Decimal) and - isinstance(currency_amount, Decimal) and - _not_same_sign(amount, currency_amount) + isinstance(amount, Decimal) + and isinstance(currency_amount, Decimal) + and _not_same_sign(amount, currency_amount) ): currency_amount *= -1 @@ -184,7 +184,7 @@ def _get_cell(self, row, index): def _iter_rows(self, file): reader = csv.reader(file, delimiter=self._delimiter, quotechar=self._quotechar) - for i in range(self._first_row_index): + for __ in range(self._first_row_index): next(reader, None) for row in reader: diff --git a/bank_statement_import_csv/models/account_journal.py b/bank_statement_import_csv/models/account_journal.py index 8d30a767..1ebc4a04 100644 --- a/bank_statement_import_csv/models/account_journal.py +++ b/bank_statement_import_csv/models/account_journal.py @@ -1,7 +1,7 @@ # © 2022 - Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, fields, models +from odoo import fields, models class AccountJournal(models.Model): diff --git a/bank_statement_import_csv/models/bank_statement_import_config.py b/bank_statement_import_csv/models/bank_statement_import_config.py index da92e9aa..94b3c2fe 100644 --- a/bank_statement_import_csv/models/bank_statement_import_config.py +++ b/bank_statement_import_csv/models/bank_statement_import_config.py @@ -1,7 +1,7 @@ # © 2022 - Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, fields, models +from odoo import fields, models class BankStatementImportConfig(models.Model): @@ -13,8 +13,7 @@ class BankStatementImportConfig(models.Model): active = fields.Boolean(default=True) first_row = fields.Integer( - default=2, - help="The position of the first transaction line in the file." + default=2, help="The position of the first transaction line in the file." ) reversed_order = fields.Boolean( help="Check this box is the lines in the csv files are ordered " @@ -75,46 +74,62 @@ def get_csv_loader_config(self): "description": { "index": self.description_column - 1, }, - "reference": { - "index": self.reference_column - 1, - } - if self.reference_enabled - else None, - "partner_name": { - "index": self.partner_name_column - 1, - } - if self.partner_name_enabled - else None, - "withdraw": { - "index": self.withdraw_column - 1, - "reverse": self.reverse_withdraw, - } - if self.withdraw_deposit_enabled - else None, - "deposit": { - "index": self.deposit_column - 1, - "reverse": self.reverse_deposit, - } - if self.withdraw_deposit_enabled - else None, - "amount": { - "index": self.amount_column - 1, - } - if not self.withdraw_deposit_enabled - else None, - "balance": { - "index": self.balance_column - 1, - } - if self.balance_enabled - else None, - "currency": { - "index": self.currency_column - 1, - } - if self.currency_amount_enabled - else None, - "currency_amount": { - "index": self.currency_amount_column - 1, - } - if self.currency_amount_enabled - else None, + "reference": ( + { + "index": self.reference_column - 1, + } + if self.reference_enabled + else None + ), + "partner_name": ( + { + "index": self.partner_name_column - 1, + } + if self.partner_name_enabled + else None + ), + "withdraw": ( + { + "index": self.withdraw_column - 1, + "reverse": self.reverse_withdraw, + } + if self.withdraw_deposit_enabled + else None + ), + "deposit": ( + { + "index": self.deposit_column - 1, + "reverse": self.reverse_deposit, + } + if self.withdraw_deposit_enabled + else None + ), + "amount": ( + { + "index": self.amount_column - 1, + } + if not self.withdraw_deposit_enabled + else None + ), + "balance": ( + { + "index": self.balance_column - 1, + } + if self.balance_enabled + else None + ), + "currency": ( + { + "index": self.currency_column - 1, + } + if self.currency_amount_enabled + else None + ), + "currency_amount": ( + { + "index": self.currency_amount_column - 1, + } + if self.currency_amount_enabled + else None + ), } diff --git a/bank_statement_import_csv/wizard/bank_statement_import_wizard.py b/bank_statement_import_csv/wizard/bank_statement_import_wizard.py index 0b5a5c13..8c9e0a2d 100644 --- a/bank_statement_import_csv/wizard/bank_statement_import_wizard.py +++ b/bank_statement_import_csv/wizard/bank_statement_import_wizard.py @@ -1,7 +1,6 @@ # © 2022 - Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -import json from base64 import b64decode from io import StringIO from odoo import api, fields, models, _ @@ -16,8 +15,7 @@ class BankStatementImportWizard(models.TransientModel): _description = "Bank Statement Import Wizard" journal_id = fields.Many2one( - "account.journal", - default=lambda self: self._context.get("journal_id") + "account.journal", default=lambda self: self._context.get("journal_id") ) config_id = fields.Many2one("bank.statement.import.config", required=True) @@ -52,7 +50,7 @@ def _compute_show_fields(self): @api.depends("line_ids") def _compute_has_error(self): for wizard in self: - wizard.has_error = any(l.has_error for l in self.line_ids) + wizard.has_error = any(line.has_error for line in self.line_ids) @api.depends("line_ids", "has_error") def _compute_is_ready(self): @@ -144,4 +142,4 @@ def _get_first_and_last_line(self): def _get_statement_line_vals(self): lines = self.line_ids - return [(0, 0, l._get_statement_line_vals()) for l in lines] + return [(0, 0, line._get_statement_line_vals()) for line in lines] diff --git a/bank_statement_no_reverse/models/account_move.py b/bank_statement_no_reverse/models/account_move.py index 6cd8054f..7f213400 100644 --- a/bank_statement_no_reverse/models/account_move.py +++ b/bank_statement_no_reverse/models/account_move.py @@ -1,7 +1,7 @@ # © 2021 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, models, _ +from odoo import models, _ from odoo.exceptions import ValidationError diff --git a/bank_statement_online_stripe/tests/test_online_bank_statement_provider.py b/bank_statement_online_stripe/tests/test_online_bank_statement_provider.py index 78c4129f..48d28eb1 100644 --- a/bank_statement_online_stripe/tests/test_online_bank_statement_provider.py +++ b/bank_statement_online_stripe/tests/test_online_bank_statement_provider.py @@ -9,7 +9,6 @@ from odoo.tests import common from odoo.exceptions import ValidationError from unittest.mock import patch -from ..interface import BalanceTransactionInterface class TestStripe(common.SavepointCase): @@ -98,13 +97,13 @@ def test_map_fee(self): def test_no_partner_email(self): self.transaction["source"]["billing_details"]["email"] = None vals = self.provider._map_stripe_transaction(self.transaction) - assert vals["partner_id"] == None + self.assertIsNone(vals["partner_id"]) assert vals["partner_name"] == self.partner_name def test_partner_not_found(self): self.partner.email = "different.email@example.com" vals = self.provider._map_stripe_transaction(self.transaction) - assert vals["partner_id"] == None + self.assertIsNone(vals["partner_id"]) def test_obtain_statement_data(self): with self._mock_balance_transaction_list(), self._mock_balance(3000): diff --git a/bank_statement_partner_name/__manifest__.py b/bank_statement_partner_name/__manifest__.py index 463acd68..c953ef6a 100644 --- a/bank_statement_partner_name/__manifest__.py +++ b/bank_statement_partner_name/__manifest__.py @@ -11,6 +11,8 @@ "category": "Accounting", "summary": "Add the partner name to bank statement lines", "depends": ["account"], - "data": ["views/bank_statement.xml",], + "data": [ + "views/bank_statement.xml", + ], "installable": True, } diff --git a/canada_bank_transfer/change_payment_date.py b/canada_bank_transfer/change_payment_date.py index fb28e38c..3c8d3fff 100644 --- a/canada_bank_transfer/change_payment_date.py +++ b/canada_bank_transfer/change_payment_date.py @@ -1,8 +1,6 @@ # © 2019 Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from datetime import date - def change_payment_date(payment, new_date): """Change the date of the payment to the given date. @@ -14,11 +12,13 @@ def change_payment_date(payment, new_date): Super user priviledges are used to prevent access right errors. """ payment_sudo = payment.sudo() - account_move = payment_sudo.mapped('move_id') - account_move.write({ - 'state': 'draft', - 'date': new_date, - }) - account_move.line_ids.write({'date_maturity': new_date}) - account_move.state = 'posted' + account_move = payment_sudo.mapped("move_id") + account_move.write( + { + "state": "draft", + "date": new_date, + } + ) + account_move.line_ids.write({"date_maturity": new_date}) + account_move.state = "posted" payment_sudo.date = new_date diff --git a/canada_bank_transfer/models/account_journal.py b/canada_bank_transfer/models/account_journal.py index d3efbe27..fed946b1 100644 --- a/canada_bank_transfer/models/account_journal.py +++ b/canada_bank_transfer/models/account_journal.py @@ -1,8 +1,7 @@ # © 2019 Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, fields, models, _ -from odoo.exceptions import ValidationError +from odoo import api, fields, models class AccountJournal(models.Model): @@ -50,8 +49,7 @@ class AccountJournal(models.Model): eft_sequence_id = fields.Many2one( "ir.sequence", string="EFT Sequence", ondelete="restrict" ) - transit_account = fields.Many2one( - "account.account", string="Transit Account") + transit_account = fields.Many2one("account.account", string="Transit Account") use_transit_account = fields.Boolean( string="Use a transit Account", compute="_get_use_transit_account" ) @@ -101,4 +99,5 @@ def _setup_eft_sequence(self): "number_increment": 1, "company_id": self.company_id.id, "implementation": "no_gap", - }) + } + ) diff --git a/canada_bank_transfer/tests/test_generate_eft.py b/canada_bank_transfer/tests/test_generate_eft.py index b4393c1f..83c09ad5 100644 --- a/canada_bank_transfer/tests/test_generate_eft.py +++ b/canada_bank_transfer/tests/test_generate_eft.py @@ -21,24 +21,30 @@ ) -@pytest.mark.parametrize('number,expected_value', [ - (10, '000001000'), - (10.23, '000001023'), - (10.234, '000001023'), - (10.235, '000001024'), - (1.49999999, '000000150') -]) +@pytest.mark.parametrize( + "number,expected_value", + [ + (10, "000001000"), + (10.23, "000001023"), + (10.234, "000001023"), + (10.235, "000001024"), + (1.49999999, "000000150"), + ], +) def test_format_payment_amount(number, expected_value): assert _format_payment_amount(number) == expected_value -@pytest.mark.parametrize('number,expected_value', [ - (10, '0000000001000'), - (10.23, '0000000001023'), - (10.234, '0000000001023'), - (10.235, '0000000001024'), - (1.49999999, '0000000000150') -]) +@pytest.mark.parametrize( + "number,expected_value", + [ + (10, "0000000001000"), + (10.23, "0000000001023"), + (10.234, "0000000001023"), + (10.235, "0000000001024"), + (1.49999999, "0000000000150"), + ], +) def test_format_total_amount(number, expected_value): assert _format_total_amount(number) == expected_value @@ -48,26 +54,26 @@ class TestFormatEFTHeader(EFTCase): def test_record_type_is_a(self): header = format_header(self.journal, 1) - assert header[0] == 'A' + assert header[0] == "A" def test_sequence_is_always_one(self): header = format_header(self.journal, 999) - assert header[1:10] == '000000001' + assert header[1:10] == "000000001" def test_user_number(self): header = format_header(self.journal, 1) assert header[10:20] == USER_NUMBER - @data(False, '123456789') + @data(False, "123456789") def test_invalid_user_number_raises_error(self, wrong_number): self.journal.eft_user_number = wrong_number with pytest.raises(ValidationError): format_header(self.journal, 1) @data( - (1, '0001'), - (999, '0999'), - (9999, '9999'), + (1, "0001"), + (999, "0999"), + (9999, "9999"), ) def test_file_number(self, data_): number, formatted_number = data_ @@ -79,8 +85,8 @@ def test_file_number_above_9999_raises_error(self): format_header(self.journal, 10000) @data( - ('2019-06-30', '019181'), - ('2020-01-01', '020001'), + ("2019-06-30", "019181"), + ("2020-01-01", "020001"), ) def test_format_header_create_date(self, data_): date, formatted_date = data_ @@ -92,7 +98,7 @@ def test_destination_data_center_code(self): header = format_header(self.journal, 1) assert header[30:35] == DESTINATION - @data(False, '1234', 'abcde') + @data(False, "1234", "abcde") def test_invalid_destination_data_center_code_raises_error(self, wrong_code): self.journal.eft_destination = wrong_code with pytest.raises(ValidationError): @@ -107,12 +113,12 @@ def test_currency_code(self): assert header[55:58] == "CAD" def test_if_no_journal_currency_then_company_currency_is_used(self): - journal = self.journal.copy({'currency_id': False}) + journal = self.journal.copy({"currency_id": False}) header = format_header(journal, 1) assert header[55:58] == journal.company_id.currency_id.name def test_currency_code_with_usd(self): - self.journal.currency_id = self.env.ref('base.USD') + self.journal.currency_id = self.env.ref("base.USD") header = format_header(self.journal, 1) assert header[55:58] == "USD" @@ -137,11 +143,11 @@ def test_record_length(self): def test_record_type_is_c(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[0] == 'C' + assert record[0] == "C" @data( - (2, '000000002'), - (999, '000000999'), + (2, "000000002"), + (999, "000000999"), ) def test_sequence_number(self, data_): number, formatted_number = data_ @@ -154,51 +160,47 @@ def test_user_number(self): def test_file_number(self): record = format_credit_details_group(self.journal, self.payments, 999, 2) - assert record[20:24] == '0999' + assert record[20:24] == "0999" def test_operation_code(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[24:27] == '450' + assert record[24:27] == "450" def test_operation_code_is_450_by_default(self): - self.payments[0].write({'eft_transaction_type': None}) + self.payments[0].write({"eft_transaction_type": None}) record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[24:27] == '450' + assert record[24:27] == "450" def test_payment_amount(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[27:37] == '0000011111' # payment 1: 111.11 - assert record[27 + 240:37 + 240] == '0000022222' # payment 2: 222.22 + assert record[27:37] == "0000011111" # payment 1: 111.11 + assert record[27 + 240 : 37 + 240] == "0000022222" # payment 2: 222.22 def test_format_header_create_date(self): - with freeze_time('2019-06-30'): + with freeze_time("2019-06-30"): self.payments[0].move_id.date = datetime.now().date() record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[37:43] == '019181' + assert record[37:43] == "019181" def test_destination_institution(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[43:47] == '0004' # '0{institution}' + assert record[43:47] == "0004" # '0{institution}' def test_destination_transit(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[47:52] == '20002' + assert record[47:52] == "20002" @data( - ('1234567', '1234567 '), - ('12345678', '12345678 '), - ('123456789012', '123456789012'), + ("1234567", "1234567 "), + ("12345678", "12345678 "), + ("123456789012", "123456789012"), ) def test_destination_account(self, data_): self.td_account.acc_number = data_[0] record = format_credit_details_group(self.journal, self.payments, 1, 2) assert record[52:64] == data_[1] - @data( - '1234567 ', # non-digit - '123456', # too short - '1234567890123' # too long - ) + @data("1234567 ", "123456", "1234567890123") # non-digit # too short # too long def test_if_account_number_too_short_raise_error(self, wrong_number): self.td_account.acc_number = wrong_number with pytest.raises(ValidationError): @@ -206,51 +208,51 @@ def test_if_account_number_too_short_raise_error(self, wrong_number): def test_zeros_from_64_to_89(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[64:89] == '0' * 25 + assert record[64:89] == "0" * 25 def test_user_short_name(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[89:104] == 'YOUR COMPANY ' # 15 caracters + assert record[89:104] == "YOUR COMPANY " # 15 caracters def test_accents_are_removed_from_user_short_name(self): - self.journal.eft_user_short_name = 'Québec Inc. *' + self.journal.eft_user_short_name = "Québec Inc. *" record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[89:104] == 'QUEBEC INC. _ ' # 15 caracters + assert record[89:104] == "QUEBEC INC. _ " # 15 caracters def test_destinator_short_name(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[104:134] == 'SUPPLIER 1 ' # 30 caracters + assert record[104:134] == "SUPPLIER 1 " # 30 caracters def test_destinator_short_name__uses_commercial_partner_name(self): self.payments[0].partner_id = self.supplier_contact self.payments[0].partner_bank_id = self.td_account record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[104:134] == 'SUPPLIER 1 ' # 30 caracters + assert record[104:134] == "SUPPLIER 1 " # 30 caracters def test_destinator_short_name__uses_acc_holder_name_if_available(self): self.payments[0].partner_bank_id.acc_holder_name = "Custom Account Holder Name" record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[104:134] == 'CUSTOM ACCOUNT HOLDER NAME ' # 30 caracters + assert record[104:134] == "CUSTOM ACCOUNT HOLDER NAME " # 30 caracters def test_accents_are_removed_from_destinator_name(self): - self.td_account.partner_id.name = '12345 Québec Inc. *test*' + self.td_account.partner_id.name = "12345 Québec Inc. *test*" record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[104:134] == '12345 QUEBEC INC. _TEST_ ' # 30 caracters + assert record[104:134] == "12345 QUEBEC INC. _TEST_ " # 30 caracters def test_user_long_name(self): - self.journal.company_id.name = 'Your Company Inc.' + self.journal.company_id.name = "Your Company Inc." record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[134:164] == 'YOUR COMPANY INC. ' # 30 caracters + assert record[134:164] == "YOUR COMPANY INC. " # 30 caracters def test_specific_user_long_name(self): - self.journal.eft_user_long_name = 'Specific User Long Name' + self.journal.eft_user_long_name = "Specific User Long Name" record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[134:164] == 'SPECIFIC USER LONG NAME ' + assert record[134:164] == "SPECIFIC USER LONG NAME " def test_accents_are_removed_from_user_long_name(self): - self.journal.company_id.name = 'Your Company Inc. *test*' + self.journal.company_id.name = "Your Company Inc. *test*" record = format_credit_details_group(self.journal, self.payments, 1, 2) - assert record[134:164] == 'YOUR COMPANY INC. _TEST_ ' # 30 caracters + assert record[134:164] == "YOUR COMPANY INC. _TEST_ " # 30 caracters def test_user_number_at_164(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) @@ -259,16 +261,16 @@ def test_user_number_at_164(self): def test_transaction_reference_number(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) reference = record[174:192] - assert reference.strip() == self.pmt_1.name.replace('/', '_') + assert reference.strip() == self.pmt_1.name.replace("/", "_") - reference_2 = record[174 + 240:192 + 240] - assert reference_2.strip() == self.pmt_2.name.replace('/', '_') + reference_2 = record[174 + 240 : 192 + 240] + assert reference_2.strip() == self.pmt_2.name.replace("/", "_") def test_transaction_reference_number_with_long_payment_name(self): - self.pmt_1.name = 'SUPP.OUT/2019/1234567' + self.pmt_1.name = "SUPP.OUT/2019/1234567" record = format_credit_details_group(self.journal, self.payments, 1, 2) reference = record[174:193] - assert reference == 'PP.OUT_2019_1234567' + assert reference == "PP.OUT_2019_1234567" def test_origin_institution(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) @@ -315,24 +317,26 @@ def setUpClass(cls): cls.pmt_4 = cls.generate_payment(cls.rbc_account, 444.44) cls.pmt_5 = cls.generate_payment(cls.rbc_account, 555.55) cls.pmt_6 = cls.generate_payment(cls.rbc_account, 666.66) - cls.payments = cls.pmt_1 | cls.pmt_2 | cls.pmt_3 | cls.pmt_4 | cls.pmt_5 | cls.pmt_6 + cls.payments = ( + cls.pmt_1 | cls.pmt_2 | cls.pmt_3 | cls.pmt_4 | cls.pmt_5 | cls.pmt_6 + ) def test_record_length(self): record = format_credit_details_group(self.journal, self.payments, 1, 2) assert len(record) == 1464 @data( - (0, '0000011111'), - (1, '0000022222'), - (2, '0000033333'), - (3, '0000044444'), - (4, '0000055555'), - (5, '0000066666'), + (0, "0000011111"), + (1, "0000022222"), + (2, "0000033333"), + (3, "0000044444"), + (4, "0000055555"), + (5, "0000066666"), ) def test_payment_amount(self, data_): record = format_credit_details_group(self.journal, self.payments, 1, 2) offset = 240 * data_[0] - assert record[27 + offset:37 + offset] == data_[1] + assert record[27 + offset : 37 + offset] == data_[1] @ddt @@ -344,11 +348,11 @@ def test_trailer_length(self): def test_record_type_is_z(self): trailer = format_trailer(self.journal, 1, 1, 1, 1) - assert trailer[0] == 'Z' + assert trailer[0] == "Z" def test_sequence_number(self): trailer = format_trailer(self.journal, 1, 123, 1, 1) - assert trailer[1:10] == '000000123' + assert trailer[1:10] == "000000123" def test_user_number(self): trailer = format_trailer(self.journal, 1, 1, 1, 1) @@ -379,7 +383,7 @@ class CompleteEFTCase(EFTCase): @classmethod def _generate_payments(cls, number_of_payments): - payments = cls.env['account.payment'] + payments = cls.env["account.payment"] for i in range(number_of_payments): payments |= cls.generate_payment(cls.rbc_account, i + 1) return payments @@ -392,19 +396,25 @@ class TestCompleteEFTLength(CompleteEFTCase): def test_eft_length_with_6_payments_or_less(self, number_of_payments): payments = self._generate_payments(number_of_payments) eft = generate_eft(self.journal, payments, 1) - assert len(eft) == 4394 # 1464 + 1464 + 1464 (header + details + trailer) + 2 \n + assert ( + len(eft) == 4394 + ) # 1464 + 1464 + 1464 (header + details + trailer) + 2 \n @data(7, 12) def test_eft_length_with_7_to_12_payments(self, number_of_payments): payments = self._generate_payments(number_of_payments) eft = generate_eft(self.journal, payments, 1) - assert len(eft) == 5859 # 1464 + 1464 * 2 + 1464 (header + details + trailer) + 3 \n + assert ( + len(eft) == 5859 + ) # 1464 + 1464 * 2 + 1464 (header + details + trailer) + 3 \n @data(13, 18) def test_eft_length_with_13_to_18_payments(self, number_of_payments): payments = self._generate_payments(number_of_payments) eft = generate_eft(self.journal, payments, 1) - assert len(eft) == 7324 # 1464 + 1464 * 3 + 1464 (header + details + trailer) + 4 \n + assert ( + len(eft) == 7324 + ) # 1464 + 1464 * 3 + 1464 (header + details + trailer) + 4 \n @ddt @@ -417,18 +427,24 @@ def setUpClass(cls): @data( # (formatted_payment_amount, amount_index_in_file) - ('0000000100', 1492), # 1492 = 1464 + 1 + 27 (header + \n + 27) - ('0000000200', 1732), # 1732 = 1492 + 240 - ('0000000500', 2452), # 2452 = 1492 + 240 * 4 - ('0000000600', 2692), # 2692 = 1492 + 240 * 5 - ('0000000700', 2957), # 2957 = 1464 + 1 + 1464 + 1 + 27 (header + \n + group1 + \n + 27) - ('0000001200', 4157), # 4157 = 2957 + 240 * 5 - ('0000001300', 4422), # 4421 = 1464 * 3 + 3 + 27 - ('0000001800', 5622), # 5622 = 4421 + 240 * 5 - ('0000001900', 5887), # 5887 = 1464 * 4 + 4 + 27 - ('0000002000', 6127), # 6127 = 5887 + 240 + ("0000000100", 1492), # 1492 = 1464 + 1 + 27 (header + \n + 27) + ("0000000200", 1732), # 1732 = 1492 + 240 + ("0000000500", 2452), # 2452 = 1492 + 240 * 4 + ("0000000600", 2692), # 2692 = 1492 + 240 * 5 + ( + "0000000700", + 2957, + ), # 2957 = 1464 + 1 + 1464 + 1 + 27 (header + \n + group1 + \n + 27) + ("0000001200", 4157), # 4157 = 2957 + 240 * 5 + ("0000001300", 4422), # 4421 = 1464 * 3 + 3 + 27 + ("0000001800", 5622), # 5622 = 4421 + 240 * 5 + ("0000001900", 5887), # 5887 = 1464 * 4 + 4 + 27 + ("0000002000", 6127), # 6127 = 5887 + 240 ) def test_payments_order(self, data_): formatted_payment_amount, amount_index_in_file = data_ eft = generate_eft(self.journal, self.payments, 1) - assert eft[amount_index_in_file:amount_index_in_file + 10] == formatted_payment_amount + assert ( + eft[amount_index_in_file : amount_index_in_file + 10] + == formatted_payment_amount + ) diff --git a/canada_bank_transfer/wizard/eft_confirmation.py b/canada_bank_transfer/wizard/eft_confirmation.py index 6ffa4ddf..da771f19 100644 --- a/canada_bank_transfer/wizard/eft_confirmation.py +++ b/canada_bank_transfer/wizard/eft_confirmation.py @@ -8,11 +8,11 @@ class EFTConfirmationWizard(models.TransientModel): - _name = 'account.eft.confirmation.wizard' - _description = 'EFT Confirmation Wizard' + _name = "account.eft.confirmation.wizard" + _description = "EFT Confirmation Wizard" - eft_id = fields.Many2one('account.eft') - line_ids = fields.One2many('account.eft.confirmation.line', 'wizard_id') + eft_id = fields.Many2one("account.eft") + line_ids = fields.One2many("account.eft.confirmation.line", "wizard_id") def action_validate(self): """Validate the EFT. @@ -24,17 +24,19 @@ def action_validate(self): * section in the form view of the EFT. * Creation journal Entries. """ - self.eft_id.state = 'done' + self.eft_id.state = "done" - completed_payments = self.line_ids.filtered( - lambda l: l.completed).mapped('payment_id') + completed_payments = self.line_ids.filtered(lambda l: l.completed).mapped( + "payment_id" + ) for payment in completed_payments: change_payment_date(payment, self.eft_id.payment_date) completed_payments.mark_as_sent() - failed_payments = self.line_ids.filtered( - lambda l: not l.completed).mapped('payment_id') + failed_payments = self.line_ids.filtered(lambda l: not l.completed).mapped( + "payment_id" + ) self.eft_id.payment_ids = completed_payments self.eft_id.failed_payment_ids = failed_payments @@ -42,8 +44,7 @@ def action_validate(self): # Creation of journal Entries if self.eft_id.use_transit_account: invoice_vals = self._prepare_account_move_values() - deposit_account_move = self.env["account.move"].create( - invoice_vals) + deposit_account_move = self.env["account.move"].create(invoice_vals) deposit_account_move.post() self.eft_id.deposit_account_move_id = deposit_account_move.id return True @@ -63,13 +64,7 @@ def _prepare_account_move_line_vals(self): """Prepare line values of EFT Entries.""" vals_account_move_lines = [] for line in self.line_ids.filtered(lambda line: line.completed): - vals_account_move_lines.append( - ( - 0, - 0, - self._get_payment_line_vals(line) - ) - ) + vals_account_move_lines.append((0, 0, self._get_payment_line_vals(line))) vals_account_move_lines.append( ( @@ -77,7 +72,11 @@ def _prepare_account_move_line_vals(self): 0, { "partner_id": self.eft_id.journal_id.company_id.partner_id.id, - "credit": sum(self.line_ids.filtered(lambda line: line.completed).mapped('amount')), + "credit": sum( + self.line_ids.filtered(lambda line: line.completed).mapped( + "amount" + ) + ), "account_id": self.eft_id.journal_id.payment_credit_account_id.id, "name": self.eft_id.name + _(" - Deposit"), }, @@ -87,43 +86,45 @@ def _prepare_account_move_line_vals(self): def _get_payment_line_vals(self, line): """Prepare line values of EFT Entries from Payments.""" - return {"partner_id": line.partner_id.id, - "debit": line.amount, - "account_id": self.eft_id.journal_id.transit_account.id, - "name": self.eft_id.name + _(" - Deposit")} + return { + "partner_id": line.partner_id.id, + "debit": line.amount, + "account_id": self.eft_id.journal_id.transit_account.id, + "name": self.eft_id.name + _(" - Deposit"), + } class EFTConfirmationLine(models.TransientModel): - _name = 'account.eft.confirmation.line' - _description = 'EFT Confirmation Line' + _name = "account.eft.confirmation.line" + _description = "EFT Confirmation Line" - wizard_id = fields.Many2one('account.eft.confirmation.wizard') - payment_id = fields.Many2one('account.payment') + wizard_id = fields.Many2one("account.eft.confirmation.wizard") + payment_id = fields.Many2one("account.payment") payment_date = fields.Date( - related='payment_id.date', + related="payment_id.date", string="Payment Date", ) name = fields.Char( - related='payment_id.name', + related="payment_id.name", string="Name", ) partner_id = fields.Many2one( - related='payment_id.partner_id', + related="payment_id.partner_id", string="Partner", ) partner_bank_account_id = fields.Many2one( - related='payment_id.partner_bank_id', + related="payment_id.partner_bank_id", string="Recipient Bank Account", ) amount = fields.Monetary( - related='payment_id.amount', + related="payment_id.amount", string="Payment Amount", ) currency_id = fields.Many2one( - related='payment_id.currency_id', + related="payment_id.currency_id", ) completed = fields.Boolean( - string='Completed', + string="Completed", default=True, ) diff --git a/canada_bank_transfer/wizard/payment_notice_email.py b/canada_bank_transfer/wizard/payment_notice_email.py index 2079fce3..d5d95852 100644 --- a/canada_bank_transfer/wizard/payment_notice_email.py +++ b/canada_bank_transfer/wizard/payment_notice_email.py @@ -1,19 +1,19 @@ # © 2019 Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import _, api, fields, models +from odoo import _, fields, models class MailComposeWizard(models.TransientModel): - _inherit = 'mail.compose.message' + _inherit = "mail.compose.message" is_eft_payment_notice = fields.Boolean() - eft_id = fields.Many2one('account.eft', 'EFT') + eft_id = fields.Many2one("account.eft", "EFT") def action_send_mail(self): result = super().action_send_mail() if self.is_eft_payment_notice: - self.eft_id.message_post(body=_('Payment notices sent.')) + self.eft_id.message_post(body=_("Payment notices sent.")) self.eft_id.payment_notices_sent = True return result diff --git a/hr_expense_tax_adjustment/models/hr_expense.py b/hr_expense_tax_adjustment/models/hr_expense.py index b5282627..d1ffa270 100644 --- a/hr_expense_tax_adjustment/models/hr_expense.py +++ b/hr_expense_tax_adjustment/models/hr_expense.py @@ -3,83 +3,95 @@ import logging from odoo import api, fields, models -from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class HrExpense(models.Model): - _inherit = 'hr.expense' + _inherit = "hr.expense" tax_line_ids = fields.One2many( - 'hr.expense.tax', 'expense_id', 'Detailed Taxes', - readonly=True, copy=True, + "hr.expense.tax", + "expense_id", + "Detailed Taxes", + readonly=True, + copy=True, states={ - 'draft': [('readonly', False)], - 'reported': [('readonly', False)], - 'refused': [('readonly', False)], - 'approved': [('readonly', False)], - }) + "draft": [("readonly", False)], + "reported": [("readonly", False)], + "refused": [("readonly", False)], + "approved": [("readonly", False)], + }, + ) @api.onchange( - 'product_id', 'quantity', 'unit_amount', 'tax_ids', - 'company_id', 'currency_id') + "product_id", "quantity", "unit_amount", "tax_ids", "company_id", "currency_id" + ) def _onchange_amount_setup_tax_lines(self): if self.quantity and self.unit_amount and self.tax_ids: self._setup_tax_lines() else: - self.tax_line_ids = self.env['hr.expense.tax'] + self.tax_line_ids = self.env["hr.expense.tax"] def _setup_tax_lines(self): """Setup the taxes on the expense.""" - self.tax_line_ids = self.env['hr.expense.tax'] + self.tax_line_ids = self.env["hr.expense.tax"] currency = self.currency_id or self.company_id.currency_id taxes = self.tax_ids.with_context(round=True).compute_all( - self.unit_amount, currency, self.quantity, self.product_id) - print("TAXES",taxes) - - for tax in taxes['taxes']: - self.tax_line_ids |= self.env['hr.expense.tax'].new({ - 'amount': tax['amount'], - 'account_id': tax['account_id'], - 'tax_id': tax['id'] or tax['id'].origin, - 'price_include': tax['price_include'], - }) + self.unit_amount, currency, self.quantity, self.product_id + ) + print("TAXES", taxes) + + for tax in taxes["taxes"]: + self.tax_line_ids |= self.env["hr.expense.tax"].new( + { + "amount": tax["amount"], + "account_id": tax["account_id"], + "tax_id": tax["id"] or tax["id"].origin, + "price_include": tax["price_include"], + } + ) def _move_line_get_using_tax_lines(self): # TODO this function must be fixed and _prepare_move_line value obsolete on v14 expense_move_line = self._prepare_move_line_value() - expense_move_line['price'] = self.untaxed_amount + expense_move_line["price"] = self.untaxed_amount move_lines = [expense_move_line] for line in self.tax_line_ids: - move_lines.append({ - 'type': 'tax', - 'name': line.tax_id.name, - 'price_unit': line.amount, - 'quantity': 1, - 'price': line.amount, - 'account_id': line.account_id.id, - 'tax_line_id': line.tax_id.id, - 'expense_id': self.id, - }) + move_lines.append( + { + "type": "tax", + "name": line.tax_id.name, + "price_unit": line.amount, + "quantity": 1, + "price": line.amount, + "account_id": line.account_id.id, + "tax_line_id": line.tax_id.id, + "expense_id": self.id, + } + ) return move_lines - @api.depends('quantity', 'unit_amount', 'tax_ids', 'currency_id', 'tax_line_ids.amount') + @api.depends( + "quantity", "unit_amount", "tax_ids", "currency_id", "tax_line_ids.amount" + ) def _compute_amount(self): expenses_with_tax_lines = self.filtered(lambda e: e.tax_ids) expenses_without_tax_lines = self.filtered(lambda e: not e.tax_ids) for expense in expenses_with_tax_lines: included_tax_amount = sum( - l.amount for l in expense.tax_line_ids if l.price_include) - tax_amount = sum(l.amount for l in expense.tax_line_ids) + line.amount for line in expense.tax_line_ids if line.price_include + ) + tax_amount = sum(line.amount for line in expense.tax_line_ids) - expense.untaxed_amount = expense.unit_amount * \ - expense.quantity - included_tax_amount + expense.untaxed_amount = ( + expense.unit_amount * expense.quantity - included_tax_amount + ) expense.total_amount = expense.untaxed_amount + tax_amount super(HrExpense, expenses_without_tax_lines)._compute_amount() diff --git a/hr_expense_tax_adjustment/tests/test_hr_expense.py b/hr_expense_tax_adjustment/tests/test_hr_expense.py index f4315cb3..ca46f2de 100644 --- a/hr_expense_tax_adjustment/tests/test_hr_expense.py +++ b/hr_expense_tax_adjustment/tests/test_hr_expense.py @@ -2,7 +2,6 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo.tests import common -from odoo.exceptions import UserError class TestAccountMoveLine(common.SavepointCase): @@ -10,87 +9,122 @@ class TestAccountMoveLine(common.SavepointCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.tax_account = cls.env['account.account'].create({ - 'code': 'TAX1', - 'name': 'Tax 1', - 'user_type_id': cls.env.ref('account.data_account_type_receivable').id, - 'reconcile': True, - }) - - cls.tax_account_2 = cls.env['account.account'].create({ - 'code': 'TAX2', - 'name': 'Tax 2', - 'user_type_id': cls.env.ref('account.data_account_type_receivable').id, - 'reconcile': True, - }) + cls.tax_account = cls.env["account.account"].create( + { + "code": "TAX1", + "name": "Tax 1", + "user_type_id": cls.env.ref("account.data_account_type_receivable").id, + "reconcile": True, + } + ) + + cls.tax_account_2 = cls.env["account.account"].create( + { + "code": "TAX2", + "name": "Tax 2", + "user_type_id": cls.env.ref("account.data_account_type_receivable").id, + "reconcile": True, + } + ) # This case of taxes is based on the GST/QST taxes in Canada - cls.tax_1 = cls.env['account.tax'].create({ - 'name': 'Tax 1 (5%)', - 'description': 'Tax 1 (5%)', - 'amount': 4.5465, - 'amount_type': 'percent', - 'type_tax_use': 'purchase', - 'price_include': True, - 'include_base_amount': False, - 'invoice_repartition_line_ids': cls._make_tax_repartition(cls.tax_account), - 'refund_repartition_line_ids': cls._make_tax_repartition(cls.tax_account), - }) - cls.tax_2 = cls.env['account.tax'].create({ - 'name': 'Tax 2 (9.9975%)', - 'description': 'Tax 2 (9.9975%)', - 'amount': 9.975, - 'amount_type': 'percent', - 'type_tax_use': 'purchase', - 'price_include': True, - 'include_base_amount': False, - 'invoice_repartition_line_ids': cls._make_tax_repartition(cls.tax_account_2), - 'refund_repartition_line_ids': cls._make_tax_repartition(cls.tax_account_2), - }) - cls.parent_tax = cls.env['account.tax'].create({ - 'name': 'Parent Tax', - 'amount': 0, - 'amount_type': 'group', - 'type_tax_use': 'purchase', - }) + cls.tax_1 = cls.env["account.tax"].create( + { + "name": "Tax 1 (5%)", + "description": "Tax 1 (5%)", + "amount": 4.5465, + "amount_type": "percent", + "type_tax_use": "purchase", + "price_include": True, + "include_base_amount": False, + "invoice_repartition_line_ids": cls._make_tax_repartition( + cls.tax_account + ), + "refund_repartition_line_ids": cls._make_tax_repartition( + cls.tax_account + ), + } + ) + cls.tax_2 = cls.env["account.tax"].create( + { + "name": "Tax 2 (9.9975%)", + "description": "Tax 2 (9.9975%)", + "amount": 9.975, + "amount_type": "percent", + "type_tax_use": "purchase", + "price_include": True, + "include_base_amount": False, + "invoice_repartition_line_ids": cls._make_tax_repartition( + cls.tax_account_2 + ), + "refund_repartition_line_ids": cls._make_tax_repartition( + cls.tax_account_2 + ), + } + ) + cls.parent_tax = cls.env["account.tax"].create( + { + "name": "Parent Tax", + "amount": 0, + "amount_type": "group", + "type_tax_use": "purchase", + } + ) cls.parent_tax.children_tax_ids = cls.tax_1 | cls.tax_2 - cls.product = cls.env.ref('hr_expense.air_ticket') + cls.product = cls.env.ref("hr_expense.air_ticket") cls.product.supplier_taxes_id = cls.parent_tax - cls.user = cls.env.ref('base.user_demo') + cls.user = cls.env.ref("base.user_demo") cls.employee = cls.user.employee_ids - cls.payable = cls.env['account.account'].search( - [('user_type_id.type', '=', 'payable')], limit=1) + cls.payable = cls.env["account.account"].search( + [("user_type_id.type", "=", "payable")], limit=1 + ) cls.employee.address_home_id.property_account_payable_id = cls.payable.id - cls.sheet = cls.env['hr.expense.sheet'].create({ - 'name': 'Air Tickets', - 'employee_id': cls.employee.id, - }) - - cls.expense = cls.env['hr.expense'].with_user(cls.user).create({ - 'name': 'Car Travel Expenses', - 'employee_id': cls.employee.id, - 'product_id': cls.product.id, - 'unit_amount': 700.00, - 'tax_ids': [(6, 0, [cls.parent_tax.id])], - 'sheet_id': cls.sheet.id, - }) + cls.sheet = cls.env["hr.expense.sheet"].create( + { + "name": "Air Tickets", + "employee_id": cls.employee.id, + } + ) + + cls.expense = ( + cls.env["hr.expense"] + .with_user(cls.user) + .create( + { + "name": "Car Travel Expenses", + "employee_id": cls.employee.id, + "product_id": cls.product.id, + "unit_amount": 700.00, + "tax_ids": [(6, 0, [cls.parent_tax.id])], + "sheet_id": cls.sheet.id, + } + ) + ) @staticmethod def _make_tax_repartition(account): return [ - (0, 0, { - "repartition_type": "base", - "factor_percent": 0, - }), - (0, 0, { - "account_id": account.id, - "factor_percent": 100, - }) + ( + 0, + 0, + { + "repartition_type": "base", + "factor_percent": 0, + }, + ), + ( + 0, + 0, + { + "account_id": account.id, + "factor_percent": 100, + }, + ), ] def test_onchangeAmountSetupTaxLines_thenTaxLinesAreComputed(self): @@ -104,7 +138,7 @@ def test_onchangeAmountSetupTaxLines_thenTaxLinesAreComputed(self): self.assertEqual(len(lines), 2) self.assertEqual(lines[0].tax_id, self.tax_1) self.assertEqual(lines[1].tax_id, self.tax_2) - base = round(700/(1 + 0.045465 + 0.09975), 2) + base = round(700 / (1 + 0.045465 + 0.09975), 2) self.assertAlmostEqual(lines[0].amount, base * 0.045465, 2) self.assertAlmostEqual(lines[1].amount, base * 0.09975, 2) @@ -136,15 +170,17 @@ def test_whenValidatingExpense_thenTaxesAreCorrectlyAccounted(self): self.assertEqual(len(move_lines), 4) tax_1 = move_lines.filtered(lambda l: l.account_id == self.tax_account) - tax_2 = move_lines.filtered( - lambda l: l.account_id == self.tax_account_2) + tax_2 = move_lines.filtered(lambda l: l.account_id == self.tax_account_2) payable = move_lines.filtered(lambda l: l.account_id == self.payable) - base = round(700/(1 + 0.045465 + 0.09975), 2) + base = round(700 / (1 + 0.045465 + 0.09975), 2) self.assertAlmostEqual(tax_1.debit, base * 0.045465, 2) self.assertAlmostEqual(tax_2.debit, base * 0.09975, 2) self.assertAlmostEqual(payable.credit, 700, 2) + # - def test_whenValidatingExpenseWithExcludedTaxes_thenTaxesAreCorrectlyAccounted(self): + def test_whenValidatingExpenseWithExcludedTaxes_thenTaxesAreCorrectlyAccounted( + self, + ): self.tax_1.amount = 5 self.tax_1.price_include = False self.tax_2.price_include = False @@ -158,14 +194,15 @@ def test_whenValidatingExpenseWithExcludedTaxes_thenTaxesAreCorrectlyAccounted(s self.assertEqual(len(move_lines), 4) tax_1 = move_lines.filtered(lambda l: l.account_id == self.tax_account) - tax_2 = move_lines.filtered( - lambda l: l.account_id == self.tax_account_2) + tax_2 = move_lines.filtered(lambda l: l.account_id == self.tax_account_2) payable = move_lines.filtered(lambda l: l.account_id == self.payable) self.assertAlmostEqual(tax_1.debit, 700 * 0.05, 2) self.assertAlmostEqual(tax_2.debit, 700 * 0.09975, 2) self.assertAlmostEqual(payable.credit, 700 * 1.14975, 2) - def test_ifTaxesAreIncludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccounted(self): + def test_ifTaxesAreIncludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccounted( + self, + ): self.sheet.approve_expense_sheets() self.sheet.action_sheet_move_create() @@ -173,14 +210,15 @@ def test_ifTaxesAreIncludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccount self.assertEqual(len(move_lines), 4) tax_1 = move_lines.filtered(lambda l: l.account_id == self.tax_account) - tax_2 = move_lines.filtered( - lambda l: l.account_id == self.tax_account_2) + tax_2 = move_lines.filtered(lambda l: l.account_id == self.tax_account_2) payable = move_lines.filtered(lambda l: l.account_id == self.payable) self.assertAlmostEqual(tax_1.debit, 700 * (0.045465 / 1.145215), 2) self.assertAlmostEqual(tax_2.debit, 700 * (0.09975 / 1.145215), 2) self.assertAlmostEqual(payable.credit, 700) - def test_ifTaxesAreExcludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccounted(self): + def test_ifTaxesAreExcludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccounted( + self, + ): self.tax_1.amount = 5 self.tax_1.price_include = False self.tax_2.price_include = False @@ -192,8 +230,7 @@ def test_ifTaxesAreExcludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccount self.assertEqual(len(move_lines), 4) tax_1 = move_lines.filtered(lambda l: l.account_id == self.tax_account) - tax_2 = move_lines.filtered( - lambda l: l.account_id == self.tax_account_2) + tax_2 = move_lines.filtered(lambda l: l.account_id == self.tax_account_2) payable = move_lines.filtered(lambda l: l.account_id == self.payable) self.assertAlmostEqual(tax_1.debit, 700 * 0.05, 2) self.assertAlmostEqual(tax_2.debit, 700 * 0.09975, 2) @@ -202,7 +239,7 @@ def test_ifTaxesAreExcludedAndExpenseHasNoTaxeLines_thenTaxesAreCorrectlyAccount def test_withMultipleExpenseLines_totalAmountsAreComputedProperly(self): self.expense._onchange_amount_setup_tax_lines() - expense_2 = self.expense.copy({'unit_amount': 500}) + expense_2 = self.expense.copy({"unit_amount": 500}) expense_2._onchange_amount_setup_tax_lines() expense_2._compute_amount() @@ -216,7 +253,7 @@ def test_withMultipleExpenseLines_totalAmountsAreComputedProperly(self): def test_withMultipleExpenseLines_taxesAreCorrectlyAccounted(self): self.expense._onchange_amount_setup_tax_lines() - expense_2 = self.expense.copy({'unit_amount': 500}) + expense_2 = self.expense.copy({"unit_amount": 500}) expense_2._onchange_amount_setup_tax_lines() expense_2.sheet_id = self.sheet @@ -226,13 +263,14 @@ def test_withMultipleExpenseLines_taxesAreCorrectlyAccounted(self): move_lines = self.sheet.account_move_id.line_ids tax_1 = move_lines.filtered(lambda l: l.account_id == self.tax_account) - tax_2 = move_lines.filtered( - lambda l: l.account_id == self.tax_account_2) + tax_2 = move_lines.filtered(lambda l: l.account_id == self.tax_account_2) payable = move_lines.filtered(lambda l: l.account_id == self.payable) total_amount = 700 + 500 - self.assertAlmostEqual(sum(tax_1.mapped('debit')), - total_amount * (0.045465 / 1.145215), 0) - self.assertAlmostEqual(sum(tax_2.mapped('debit')), - total_amount * (0.09975 / 1.145215), 0) - self.assertAlmostEqual(sum(payable.mapped('credit')), total_amount, 0) + self.assertAlmostEqual( + sum(tax_1.mapped("debit")), total_amount * (0.045465 / 1.145215), 0 + ) + self.assertAlmostEqual( + sum(tax_2.mapped("debit")), total_amount * (0.09975 / 1.145215), 0 + ) + self.assertAlmostEqual(sum(payable.mapped("credit")), total_amount, 0) diff --git a/invoice_currency_validation/models/account_move.py b/invoice_currency_validation/models/account_move.py index 3d7868a1..da23e63f 100644 --- a/invoice_currency_validation/models/account_move.py +++ b/invoice_currency_validation/models/account_move.py @@ -2,9 +2,8 @@ # © 2018 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import _, api, models +from odoo import _, models from odoo.exceptions import UserError -from typing import Optional class AccountMove(models.Model): @@ -44,7 +43,8 @@ def _check_invoice_currency_versus_account_currency(self): invoice_currency = self.currency_id or company_currency partner_lines = self.line_ids.filtered( - lambda l: l.account_id.internal_type in ( + lambda l: l.account_id.internal_type + in ( "receivable", "payable", ) diff --git a/invoice_intercompany_compatible/tests/test_account_invoice.py b/invoice_intercompany_compatible/tests/test_account_invoice.py index 5d1797f3..9c05f534 100644 --- a/invoice_intercompany_compatible/tests/test_account_invoice.py +++ b/invoice_intercompany_compatible/tests/test_account_invoice.py @@ -1,7 +1,7 @@ # © 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo.tests.common import SavepointCase, Form +from odoo.tests.common import SavepointCase class TestAccountInvoice(SavepointCase): diff --git a/invoice_list_email/__manifest__.py b/invoice_list_email/__manifest__.py index c60f0fe6..4716cb7c 100644 --- a/invoice_list_email/__manifest__.py +++ b/invoice_list_email/__manifest__.py @@ -11,6 +11,8 @@ "category": "Accounting", "summary": "Add the email to the list of customer invoices", "depends": ["account"], - "data": ["views/account_move.xml",], + "data": [ + "views/account_move.xml", + ], "installable": True, } diff --git a/invoice_mass_mailing_with_layout/tests/__init__.py b/invoice_mass_mailing_with_layout/tests/__init__.py index 72c8ae9c..65c2064a 100644 --- a/invoice_mass_mailing_with_layout/tests/__init__.py +++ b/invoice_mass_mailing_with_layout/tests/__init__.py @@ -1,4 +1,4 @@ # © 2022 Numigi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from . import test_account_invoice_send \ No newline at end of file +from . import test_account_invoice_send diff --git a/invoice_mass_mailing_with_layout/tests/test_account_invoice_send.py b/invoice_mass_mailing_with_layout/tests/test_account_invoice_send.py index 93396f72..07748127 100644 --- a/invoice_mass_mailing_with_layout/tests/test_account_invoice_send.py +++ b/invoice_mass_mailing_with_layout/tests/test_account_invoice_send.py @@ -9,7 +9,8 @@ class TestAccountInvoice(SavepointCase): def setUpClass(cls): super().setUpClass() cls.invoices = cls.env["account.move"].search( - [("move_type", "=", "out_invoice")]) + [("move_type", "=", "out_invoice")] + ) cls.template = cls.env.ref("account.email_template_edi_invoice") cls.template.auto_delete = False @@ -42,7 +43,10 @@ def _create_wizard(self, invoices): def _find_last_email(self, invoice): return self.env["mail.mail"].search( - [("model", "=", "account.move"), ("res_id", "=", invoice.id),], + [ + ("model", "=", "account.move"), + ("res_id", "=", invoice.id), + ], order="id desc", limit=1, ) diff --git a/payment_list_not_sent/__manifest__.py b/payment_list_not_sent/__manifest__.py index e05957e2..f0dfd7d9 100644 --- a/payment_list_not_sent/__manifest__.py +++ b/payment_list_not_sent/__manifest__.py @@ -11,6 +11,8 @@ "category": "Accounting", "summary": "Easily view supplier payments not sent from list view", "depends": ["account"], - "data": ["views/account_payment.xml",], + "data": [ + "views/account_payment.xml", + ], "installable": True, }