diff --git a/account_move_template/__manifest__.py b/account_move_template/__manifest__.py index d1d47105..ea722b37 100644 --- a/account_move_template/__manifest__.py +++ b/account_move_template/__manifest__.py @@ -7,8 +7,8 @@ 'version': '11.0.1.0.0', 'category': 'Generic Modules/Accounting', 'summary': "Templates for recurring Journal Entries", - 'author': "Agile Business Group,Odoo Community Association (OCA), Aurium " - "Technologies,Vauxoo", + 'author': "Agile Business Group, Odoo Community Association (OCA), Aurium " + "Technologies, Vauxoo, Eficent", 'website': 'https://github.com/OCA/account-financial-tools', 'license': 'AGPL-3', 'depends': [ @@ -19,6 +19,7 @@ 'security/ir.model.access.csv', 'view/move_template.xml', 'wizard/select_template.xml', + 'security/account_move_template_security.xml', ], 'test': [ ], diff --git a/account_move_template/models/account_document_template.py b/account_move_template/models/account_document_template.py index 55fc4751..752d8791 100644 --- a/account_move_template/models/account_document_template.py +++ b/account_move_template/models/account_document_template.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 See manifest +# Copyright 2015-2018 See manifest # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from functools import partial @@ -10,7 +10,14 @@ from odoo.tools.safe_eval import safe_eval class AccountDocumentTemplate(models.Model): _name = 'account.document.template' - name = fields.Char(required=True) + name = fields.Char('Name', required=True, + ) + + @api.multi + def copy(self, default=None): + self.ensure_one() + default = dict(default or {}, name=_('%s (copy)') % self.name) + return super(AccountDocumentTemplate, self).copy(default) @api.multi def _input_lines(self): @@ -76,10 +83,13 @@ class AccountDocumentTemplate(models.Model): class AccountDocumentTemplateLine(models.Model): _name = 'account.document.template.line' - name = fields.Char(required=True) - sequence = fields.Integer(required=True) + name = fields.Char('Name', required=True, + ) + sequence = fields.Integer('Sequence', required=True, + ) type = fields.Selection([ ('computed', 'Computed'), ('input', 'User input'), - ], required=True, default='input') - python_code = fields.Text() + ], string='Type', required=True, default='input', + ) + python_code = fields.Text('Python code') diff --git a/account_move_template/models/account_move_template.py b/account_move_template/models/account_move_template.py index 4f61c4f8..26568003 100644 --- a/account_move_template/models/account_move_template.py +++ b/account_move_template/models/account_move_template.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 See manifest +# Copyright 2015-2018 See manifest # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from odoo import models, fields, api @@ -35,17 +35,26 @@ class AccountMoveTemplate(models.Model): action.update({'context': {'default_template_id': self.id}}) return action + _sql_constraints = [ + ('sequence_move_template_uniq', 'unique (name,company_id)', + 'The name of the template must be unique per company !') + ] + class AccountMoveTemplateLine(models.Model): _name = 'account.move.template.line' _inherit = 'account.document.template.line' + company_id = fields.Many2one('res.company', + related='template_id.company_id', + readonly=True) journal_id = fields.Many2one('account.journal', required=True) account_id = fields.Many2one( 'account.account', required=True, ondelete="cascade" ) + partner_id = fields.Many2one('res.partner', string='Partner') move_line_type = fields.Selection( [('cr', 'Credit'), ('dr', 'Debit')], required=True @@ -54,6 +63,11 @@ class AccountMoveTemplateLine(models.Model): 'account.analytic.account', ondelete="cascade" ) + analytic_tag_ids = fields.Many2many('account.analytic.tag', + string='Analytic tags') + tax_ids = fields.Many2many('account.tax', string='Taxes') + tax_line_id = fields.Many2one('account.tax', string='Originator tax', + ondelete='restrict') template_id = fields.Many2one('account.move.template') _sql_constraints = [ diff --git a/account_move_template/readme/CONTRIBUTORS.rst b/account_move_template/readme/CONTRIBUTORS.rst index 7df9093c..63c6c51f 100644 --- a/account_move_template/readme/CONTRIBUTORS.rst +++ b/account_move_template/readme/CONTRIBUTORS.rst @@ -12,4 +12,5 @@ Contributors * Jalal ZAHID (port to v10) * Alex Comba (Port to V8) * Guewen Baconnier -* Raf Ven (port to v11) \ No newline at end of file +* Raf Ven (port to v11) +* Jordi Ballester (EFICENT) \ No newline at end of file diff --git a/account_move_template/security/account_move_template_security.xml b/account_move_template/security/account_move_template_security.xml new file mode 100644 index 00000000..b706266c --- /dev/null +++ b/account_move_template/security/account_move_template_security.xml @@ -0,0 +1,11 @@ + + + + + Move Template multi company rule + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + diff --git a/account_move_template/tests/__init__.py b/account_move_template/tests/__init__.py new file mode 100644 index 00000000..83734184 --- /dev/null +++ b/account_move_template/tests/__init__.py @@ -0,0 +1,2 @@ + +from . import test_account_move_template diff --git a/account_move_template/tests/test_account_move_template.py b/account_move_template/tests/test_account_move_template.py new file mode 100644 index 00000000..5fcc32e3 --- /dev/null +++ b/account_move_template/tests/test_account_move_template.py @@ -0,0 +1,184 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging +from psycopg2 import IntegrityError +from odoo.tests.common import TransactionCase +from odoo.tools import mute_logger +from odoo import fields + +_logger = logging.getLogger(__name__) + + +class TestAccountMoveTemplate(TransactionCase): + + def with_context(self, *args, **kwargs): + context = dict(args[0] if args else self.env.context, **kwargs) + self.env = self.env(context=context) + return self + + def _chart_of_accounts_create(self, company, chart): + _logger.debug('Creating chart of account') + self.env.user.write({ + 'company_ids': [(4, company.id)], + 'company_id': company.id, + }) + self.with_context( + company_id=company.id, force_company=company.id) + wizard = self.env['wizard.multi.charts.accounts'].create({ + 'company_id': company.id, + 'chart_template_id': chart.id, + 'code_digits': 6, + 'currency_id': self.env.ref('base.EUR').id, + 'transfer_account_id': chart.transfer_account_id.id, + }) + wizard.onchange_chart_template_id() + wizard.execute() + return True + + def setUp(self): + super(TestAccountMoveTemplate, self).setUp() + employees_group = self.env.ref('base.group_user') + multi_company_group = self.env.ref('base.group_multi_company') + account_user_group = self.env.ref('account.group_account_user') + account_manager_group = self.env.ref('account.group_account_manager') + self.company = self.env['res.company'].create({ + 'name': 'Test company', + }) + self.company_2 = self.env['res.company'].create({ + 'name': 'Test company 2', + 'parent_id': self.company.id, + }) + self.env.user.company_ids += self.company + self.env.user.company_ids += self.company_2 + + self.user = self.env['res.users'].sudo(self.env.user).with_context( + no_reset_password=True).create( + {'name': 'Test User', + 'login': 'test_user', + 'email': 'test@oca.com', + 'groups_id': [(6, 0, [employees_group.id, + account_user_group.id, + account_manager_group.id, + multi_company_group.id, + ])], + 'company_id': self.company.id, + 'company_ids': [(4, self.company.id)], + }) + + self.user_type = self.env.ref('account.data_account_type_liquidity') + + self.chart = self.env['account.chart.template'].search([], limit=1) + self._chart_of_accounts_create(self.company, self.chart) + account_template = self.env['account.account.template'].create({ + 'name': 'Test 1', + 'code': 'Code_test', + 'user_type_id': self.user_type.id, + }) + self.env['ir.model.data'].create({ + 'name': account_template.name, + 'module': 'account', + 'model': 'account.account.template', + 'res_id': account_template.id, + 'noupdate': 0, + }) + + self.chart_2 = self.env['account.chart.template'].create({ + 'name': 'Test Chart', + 'currency_id': self.env.ref('base.EUR').id, + 'transfer_account_id': account_template.id, + }) + + account_template.chart_template_id = self.chart_2 + self.chart_2.tax_template_ids |= self.chart.tax_template_ids + + self._chart_of_accounts_create(self.company_2, self.chart_2) + + self.chart.company_id = self.company + self.chart_2.company_id = self.company_2 + + self.account_company_1 = self.env['account.account'].search( + [('company_id', '=', self.company.id)], limit=1) + self.account_journal_1 = self.env['account.journal'].create({ + 'name': 'Journal Company 1', + 'company_id': self.company.id, + 'code': 'TST', + 'type': 'general', + }) + self.partner = self.env['res.partner'].create({ + 'name': 'Test partner', + 'company_id': False, + }) + self.partner2 = self.env['res.partner'].create({ + 'name': 'Test partner 2', + 'company_id': False, + }) + self.account_type = self.env['account.account.type'].create({ + 'name': 'Test Tax Account Type'}) + + self.tax_account_id = self.env['account.account'].create({ + 'name': 'tax account', + 'code': 'TAX', + 'user_type_id': self.account_type.id, + 'company_id': self.company.id, + }) + self.tax = self.env['account.tax'].create({ + 'name': 'Tax 10.0%', + 'amount': 10.0, + 'amount_type': 'percent', + 'account_id': self.tax_account_id.id, + }) + + def test_create_template(self): + """Test that I can create a template + """ + template = self.env['account.move.template'].sudo(self.user).create({ + 'name': 'Test Move Template', + 'company_id': self.company.id, + 'template_line_ids': [ + (0, 0, { + 'name': 'L1', + 'sequence': 1, + 'journal_id': self.account_journal_1.id, + 'account_id': self.account_company_1.id, + 'partner_id': self.partner.id, + 'tax_line_id': self.tax.id, + 'move_line_type': 'dr', + 'type': 'input' + }), + (0, 0, { + 'name': 'L2', + 'sequence': 2, + 'journal_id': self.account_journal_1.id, + 'account_id': self.account_company_1.id, + 'move_line_type': 'cr', + 'tax_ids': [(4, self.tax.id)], + 'type': 'input', + }) + ] + }) + + self.assertEquals(template.company_id, self.user.company_id) + + template_2 = template.copy() + self.assertEquals(template_2.name, '%s (copy)' % template.name) + + wiz = self.env['wizard.select.move.template'].sudo(self.user).create({ + 'company_id': self.company.id, + 'template_id': template.id, + 'partner_id': self.partner2.id, + 'date': fields.Date.today(), + }) + wiz.load_lines() + res = wiz.load_template() + aml = self.env['account.move.line'].search( + [('account_id', '=', self.account_company_1.id)], limit=1) + self.assertEquals(res['domain'], ([('id', 'in', aml.move_id.ids)])) + aml = self.env['account.move.line'].search( + [('name', '=', 'L1')], limit=1) + self.assertEquals(aml.tax_line_id, self.tax) + self.assertEquals(aml.partner_id, self.partner) + aml = self.env['account.move.line'].search( + [('name', '=', 'L2')], limit=1) + self.assertEquals(aml.tax_ids[0], self.tax) + with self.assertRaises(IntegrityError), mute_logger('odoo.sql_db'): + template_2.name = template.name diff --git a/account_move_template/view/move_template.xml b/account_move_template/view/move_template.xml index 3f674f6c..1bc491ce 100644 --- a/account_move_template/view/move_template.xml +++ b/account_move_template/view/move_template.xml @@ -7,12 +7,17 @@ - - - + + + + + + + - + + @@ -27,14 +32,23 @@ - - - + + + + + + + + + + + +