diff --git a/account_asset_batch_compute/__init__.py b/account_asset_batch_compute/__init__.py new file mode 100644 index 000000000..976591c99 --- /dev/null +++ b/account_asset_batch_compute/__init__.py @@ -0,0 +1,2 @@ +from . import wizards +from . import models diff --git a/account_asset_batch_compute/__manifest__.py b/account_asset_batch_compute/__manifest__.py new file mode 100644 index 000000000..7aa0d5056 --- /dev/null +++ b/account_asset_batch_compute/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2016-2017 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Account Asset Batch Compute', + 'summary': """ + Add the possibility to compute assets in batch""", + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'ACSONE SA/NV,' + 'Eficent,' + 'Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/account-financial-tools', + 'depends': [ + 'account_asset_management', + 'queue_job', + ], + 'data': [ + 'wizards/account_asset_compute_views.xml', + ], +} diff --git a/account_asset_batch_compute/models/__init__.py b/account_asset_batch_compute/models/__init__.py new file mode 100644 index 000000000..02a692c62 --- /dev/null +++ b/account_asset_batch_compute/models/__init__.py @@ -0,0 +1 @@ +from . import account_asset diff --git a/account_asset_batch_compute/models/account_asset.py b/account_asset_batch_compute/models/account_asset.py new file mode 100644 index 000000000..49440fae0 --- /dev/null +++ b/account_asset_batch_compute/models/account_asset.py @@ -0,0 +1,37 @@ +# Copyright 2016 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models, _ + +import logging +_logger = logging.getLogger(__name__) + +try: + from odoo.addons.queue_job.job import job +except ImportError: + _logger.debug('Can not `import queue_job`.') + + +class AccountAsset(models.Model): + + _inherit = 'account.asset' + + @api.multi + @job(default_channel='root.account_asset_batch_compute') + def _compute_entries(self, date_end, check_triggers=False): + if self.env.context.get( + 'asset_batch_processing', False + ) and not self.env.context.get('test_queue_job_no_delay', False): + results = [] + log_error = '' + for record in self: + description =\ + _("Creating move for asset with id %s to %s") %\ + (record.id, date_end) + record.with_delay( + description=description)._compute_entries( + date_end, check_triggers=check_triggers) + return results, log_error + else: + return super(AccountAsset, self)._compute_entries( + date_end, check_triggers=check_triggers) diff --git a/account_asset_batch_compute/readme/CONTRIBUTORS.rst b/account_asset_batch_compute/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..615367e6f --- /dev/null +++ b/account_asset_batch_compute/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Adrien Peiffer +* Jordi Ballester Alomar diff --git a/account_asset_batch_compute/readme/DESCRIPTION.rst b/account_asset_batch_compute/readme/DESCRIPTION.rst new file mode 100644 index 000000000..598f9c666 --- /dev/null +++ b/account_asset_batch_compute/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +Add the possibility to compute assets in batch. +This module adds a flag on compute assets wizard in order to execute +this process in batch. + diff --git a/account_asset_batch_compute/static/description/icon.svg b/account_asset_batch_compute/static/description/icon.svg new file mode 100644 index 000000000..a7a26d093 --- /dev/null +++ b/account_asset_batch_compute/static/description/icon.svg @@ -0,0 +1,79 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/account_asset_batch_compute/tests/__init__.py b/account_asset_batch_compute/tests/__init__.py new file mode 100644 index 000000000..a1df88209 --- /dev/null +++ b/account_asset_batch_compute/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_asset_batch_compute diff --git a/account_asset_batch_compute/tests/test_account_asset_batch_compute.py b/account_asset_batch_compute/tests/test_account_asset_batch_compute.py new file mode 100644 index 000000000..68cb95b1c --- /dev/null +++ b/account_asset_batch_compute/tests/test_account_asset_batch_compute.py @@ -0,0 +1,120 @@ +# Copyright 2016-19 ACSONE SA/NV +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import time +from odoo.tests.common import TransactionCase +from datetime import date +from dateutil import relativedelta + +from odoo.addons.queue_job.job import Job + + +class TestAccountAssetBatchCompute(TransactionCase): + + def setUp(self): + super(TestAccountAssetBatchCompute, self).setUp() + self.wiz_obj = self.env['account.asset.compute'] + self.asset_model = self.env['account.asset'] + self.asset_profile_model = self.env['account.asset.profile'] + self.account_account_type_model = self.env['account.account.type'] + self.account_type_regular = self.account_account_type_model.create({ + 'name': 'Test Regular', + 'type': 'other', + }) + self.account = self.env['account.account'].create({ + 'name': 'Test account', + 'code': 'TAC', + 'user_type_id': self.account_type_regular.id, + }) + self.journal = self.env['account.journal'].create({ + 'name': 'Test Journal', + 'code': 'TJ', + 'type': 'general', + }) + self.profile = self.asset_profile_model.create({ + 'account_expense_depreciation_id': self.account.id, + 'account_asset_id': self.account.id, + 'account_depreciation_id': self.account.id, + 'journal_id': self.journal.id, + 'name': "Test", + }) + self.fiscal_year = self.env['account.fiscal.year'].create({ + 'name': 'FY', + 'date_from': time.strftime('2019-01-01'), + 'date_to': time.strftime('2019-12-31'), + }) + self.asset01 = self.asset_model.create({ + 'name': 'test asset', + 'profile_id': self.profile.id, + 'purchase_value': 1000, + 'salvage_value': 0, + 'date_start': time.strftime('2003-01-01'), + 'method_time': 'year', + 'method_number': 1, + 'method_period': 'month', + 'prorata': False, + }) + today = date.today() + first_day_of_month = date(today.year, today.month, 1) + self.nextmonth = first_day_of_month + relativedelta.relativedelta( + months=1) + self.asset01.date_start = first_day_of_month + + def test_1(self): + wiz = self.wiz_obj.create({'batch_processing': False, + 'date_end': self.nextmonth}) + # I check if this asset is draft + self.assertEqual(self.asset01.state, 'draft') + # I confirm this asset + self.asset01.validate() + # I check if this asset is running + self.assertEqual(self.asset01.state, 'open') + self.asset01.compute_depreciation_board() + # I check that there is no depreciation line + depreciation_line = self.asset01.depreciation_line_ids\ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertTrue(len(depreciation_line) == 0) + wiz.asset_compute() + depreciation_line = self.asset01.depreciation_line_ids\ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertTrue(len(depreciation_line) == 1) + + def test_2(self): + wiz = self.wiz_obj.create({'batch_processing': True, + 'date_end': self.nextmonth}) + # I check if this asset is draft + self.assertEqual(self.asset01.state, 'draft') + # I confirm this asset + self.asset01.validate() + # I check if this asset is running + self.assertEqual(self.asset01.state, 'open') + self.asset01.compute_depreciation_board() + # I check that there is no depreciation line + depreciation_line = self.asset01.depreciation_line_ids\ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertTrue(len(depreciation_line) == 0) + wiz.with_context(test_queue_job_no_delay=False).asset_compute() + depreciation_line = self.asset01.depreciation_line_ids \ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertTrue(len(depreciation_line) == 0) + job_name = "Creating jobs to create moves for assets to %s" % ( + self.nextmonth) + jobs = self.env['queue.job'].search( + [('name', '=', job_name)], order='date_created desc', limit=1) + self.assertTrue(len(jobs) == 1) + job = Job.load(self.env, jobs.uuid) + # perform job + job.perform() + depreciation_line = self.asset01.depreciation_line_ids \ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertTrue(len(depreciation_line) == 0) + job_name = "Creating move for asset with id %s to %s" % ( + self.asset01.id, self.nextmonth) + jobs = self.env['queue.job'].search( + [('name', '=', job_name)], order='date_created desc', limit=1) + self.assertTrue(len(jobs) == 1) + job = Job.load(self.env, jobs.uuid) + job.perform() + depreciation_line = self.asset01.depreciation_line_ids \ + .filtered(lambda r: r.type == 'depreciate' and r.move_id) + self.assertEquals(len(depreciation_line), 1) diff --git a/account_asset_batch_compute/wizards/__init__.py b/account_asset_batch_compute/wizards/__init__.py new file mode 100644 index 000000000..07bfe6b38 --- /dev/null +++ b/account_asset_batch_compute/wizards/__init__.py @@ -0,0 +1 @@ +from . import account_asset_compute diff --git a/account_asset_batch_compute/wizards/account_asset_compute.py b/account_asset_batch_compute/wizards/account_asset_compute.py new file mode 100644 index 000000000..bae67dee7 --- /dev/null +++ b/account_asset_batch_compute/wizards/account_asset_compute.py @@ -0,0 +1,38 @@ +# Copyright 2016-2017 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ + +import logging +_logger = logging.getLogger(__name__) + +try: + from odoo.addons.queue_job.job import job +except ImportError: + _logger.debug('Can not `import queue_job`.') + + +class AccountAssetCompute(models.TransientModel): + + _inherit = 'account.asset.compute' + + batch_processing = fields.Boolean() + + @api.multi + @job(default_channel='root.account_asset_batch_compute') + def asset_compute(self): + self.ensure_one() + if not self.batch_processing: + return super(AccountAssetCompute, self).asset_compute() + if not self.env.context.get('job_uuid') and not self.env.context.get( + 'test_queue_job_no_delay' + ): + description = \ + _("Creating jobs to create moves for assets to %s") % ( + self.date_end,) + job = self.with_delay(description=description).asset_compute() + return u'Job created with uuid %s' % (job.uuid,) + else: + return super( + AccountAssetCompute, self.with_context( + asset_batch_processing=True)).asset_compute() diff --git a/account_asset_batch_compute/wizards/account_asset_compute_views.xml b/account_asset_batch_compute/wizards/account_asset_compute_views.xml new file mode 100644 index 000000000..e06181e1a --- /dev/null +++ b/account_asset_batch_compute/wizards/account_asset_compute_views.xml @@ -0,0 +1,18 @@ + + + + + + + account.asset.compute (in account_asset_batch_compute) + account.asset.compute + + + + + + + + + diff --git a/oca_dependencies.txt b/oca_dependencies.txt index c788c80e5..e0eb391a0 100644 --- a/oca_dependencies.txt +++ b/oca_dependencies.txt @@ -1,3 +1,4 @@ +queue server-ux server-tools queue