[MIG] account_move_template from v11 to v12 (full re-write)
This commit is contained in:
parent
7f35b8a9ee
commit
d2da4f4276
@ -1,27 +1,25 @@
|
|||||||
# Copyright 2015-2017 See manifest
|
# Copyright 2015-2017 See manifest
|
||||||
# Copyright 2018 Raf Ven <raf.ven@dynapps.be>
|
# Copyright 2018 Raf Ven <raf.ven@dynapps.be>
|
||||||
|
# Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': "Account Move Template",
|
'name': "Account Move Template",
|
||||||
'version': '11.0.1.0.0',
|
'version': '12.0.1.0.0',
|
||||||
'category': 'Generic Modules/Accounting',
|
'category': 'Accounting',
|
||||||
'summary': "Templates for recurring Journal Entries",
|
'summary': "Templates for recurring Journal Entries",
|
||||||
'author': "Agile Business Group, Odoo Community Association (OCA), Aurium "
|
'author': "Agile Business Group, Odoo Community Association (OCA), Aurium "
|
||||||
"Technologies, Vauxoo, Eficent",
|
"Technologies, Vauxoo, Eficent, Akretion",
|
||||||
'website': 'https://github.com/OCA/account-financial-tools',
|
'website': 'https://github.com/OCA/account-financial-tools',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'depends': [
|
'depends': [
|
||||||
'account',
|
'account',
|
||||||
'analytic',
|
|
||||||
],
|
],
|
||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
|
||||||
'view/move_template.xml',
|
|
||||||
'wizard/select_template.xml',
|
|
||||||
'security/account_move_template_security.xml',
|
'security/account_move_template_security.xml',
|
||||||
],
|
'security/ir.model.access.csv',
|
||||||
'test': [
|
'wizard/account_move_template_run_view.xml',
|
||||||
|
'view/account_move_template.xml',
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1 @@
|
|||||||
from . import account_document_template
|
|
||||||
from . import account_move_template
|
from . import account_move_template
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
# Copyright 2015-2018 See manifest
|
|
||||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
import re
|
|
||||||
from odoo import models, fields, api, exceptions, _
|
|
||||||
from odoo.tools.safe_eval import safe_eval
|
|
||||||
|
|
||||||
|
|
||||||
class AccountDocumentTemplate(models.Model):
|
|
||||||
_name = 'account.document.template'
|
|
||||||
|
|
||||||
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):
|
|
||||||
count = 0
|
|
||||||
for line in self.template_line_ids:
|
|
||||||
if line.type == 'input':
|
|
||||||
count += 1
|
|
||||||
return count
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_template_line(self, line_number):
|
|
||||||
for line in self.template_line_ids:
|
|
||||||
if line.sequence == line_number:
|
|
||||||
return line
|
|
||||||
return False
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _generate_empty_lines(self):
|
|
||||||
lines = {}
|
|
||||||
for line in self.template_line_ids:
|
|
||||||
lines[line.sequence] = None
|
|
||||||
return lines
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def lines(self, line_number, computed_lines=None):
|
|
||||||
if computed_lines is None:
|
|
||||||
computed_lines = {}
|
|
||||||
if computed_lines[line_number] is not None:
|
|
||||||
return computed_lines[line_number]
|
|
||||||
line = self._get_template_line(line_number)
|
|
||||||
if re.match(r'L\( *' + str(line_number) + r' *\)', line.python_code):
|
|
||||||
raise exceptions.Warning(
|
|
||||||
_('Line %s can\'t refer to itself') % str(line_number)
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
recurse_lines = partial(self.lines, computed_lines=computed_lines)
|
|
||||||
computed_lines[line_number] = safe_eval(
|
|
||||||
line.python_code.replace('L', 'recurse_lines'),
|
|
||||||
locals_dict={'recurse_lines': recurse_lines}
|
|
||||||
)
|
|
||||||
except KeyError:
|
|
||||||
raise exceptions.Warning(
|
|
||||||
_('Code "%s" refers to non existing line') % line.python_code)
|
|
||||||
return computed_lines[line_number]
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def compute_lines(self, input_lines):
|
|
||||||
if len(input_lines) != self._input_lines():
|
|
||||||
raise exceptions.Warning(
|
|
||||||
_('You can not add a different number of lines in this wizard '
|
|
||||||
'you should try to create the move normally and then edit '
|
|
||||||
'the created move. Inconsistent between input lines and '
|
|
||||||
' filled lines for template %s') % self.name
|
|
||||||
)
|
|
||||||
computed_lines = self._generate_empty_lines()
|
|
||||||
computed_lines.update(input_lines)
|
|
||||||
for line_number in computed_lines:
|
|
||||||
computed_lines[line_number] = self.lines(
|
|
||||||
line_number, computed_lines)
|
|
||||||
return computed_lines
|
|
||||||
|
|
||||||
|
|
||||||
class AccountDocumentTemplateLine(models.Model):
|
|
||||||
_name = 'account.document.template.line'
|
|
||||||
|
|
||||||
name = fields.Char('Name', required=True,
|
|
||||||
)
|
|
||||||
sequence = fields.Integer('Sequence', required=True,
|
|
||||||
)
|
|
||||||
type = fields.Selection([
|
|
||||||
('computed', 'Computed'),
|
|
||||||
('input', 'User input'),
|
|
||||||
], string='Type', required=True, default='input',
|
|
||||||
)
|
|
||||||
python_code = fields.Text('Python code')
|
|
@ -1,79 +1,133 @@
|
|||||||
# Copyright 2015-2018 See manifest
|
# Copyright 2015-2019 See manifest
|
||||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
from odoo import models, fields, api
|
from odoo import api, fields, models, _
|
||||||
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
from odoo.exceptions import UserError, ValidationError
|
||||||
|
from odoo.tools import float_round
|
||||||
|
|
||||||
|
|
||||||
class AccountMoveTemplate(models.Model):
|
class AccountMoveTemplate(models.Model):
|
||||||
_name = 'account.move.template'
|
_name = 'account.move.template'
|
||||||
_inherit = ['account.document.template',
|
_description = 'Journal Entry Template'
|
||||||
# 'mail.activity.mixin', TODO: uncomment for saas-15
|
|
||||||
'mail.thread']
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _company_get(self):
|
|
||||||
return self.env['res.company']._company_default_get(
|
|
||||||
object='account.move.template'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
name = fields.Char(required=True)
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
'res.company',
|
'res.company', string='Company', required=True, ondelete='cascade',
|
||||||
required=True,
|
default=lambda self: self.env['res.company']._company_default_get())
|
||||||
change_default=True,
|
journal_id = fields.Many2one(
|
||||||
default=_company_get,
|
'account.journal', string='Journal', required=True)
|
||||||
)
|
ref = fields.Char(string='Reference', copy=False)
|
||||||
journal_id = fields.Many2one('account.journal', required=True)
|
line_ids = fields.One2many(
|
||||||
template_line_ids = fields.One2many(
|
'account.move.template.line', inverse_name='template_id',
|
||||||
'account.move.template.line',
|
string='Lines')
|
||||||
inverse_name='template_id',
|
|
||||||
)
|
|
||||||
|
|
||||||
@api.multi
|
_sql_constraints = [(
|
||||||
def action_run_template(self):
|
'name_company_unique',
|
||||||
|
'unique(name, company_id)',
|
||||||
|
'This name is already used by another template!'
|
||||||
|
)]
|
||||||
|
|
||||||
|
def copy(self, default=None):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
action = self.env.ref(
|
default = dict(default or {}, name=_('%s (copy)') % self.name)
|
||||||
'account_move_template.action_wizard_select_template').read()[0]
|
return super(AccountMoveTemplate, self).copy(default)
|
||||||
action.update({'context': {'default_template_id': self.id}})
|
|
||||||
return action
|
|
||||||
|
|
||||||
_sql_constraints = [
|
def eval_computed_line(self, line, sequence2amount):
|
||||||
('sequence_move_template_uniq', 'unique (name,company_id)',
|
safe_eval_dict = {}
|
||||||
'The name of the template must be unique per company !')
|
for seq, amount in sequence2amount.items():
|
||||||
]
|
safe_eval_dict['L%d' % seq] = amount
|
||||||
|
try:
|
||||||
|
val = safe_eval(line.python_code, safe_eval_dict)
|
||||||
|
sequence2amount[line.sequence] = val
|
||||||
|
except ValueError:
|
||||||
|
raise UserError(_(
|
||||||
|
"Impossible to compute the formula of line with sequence %s "
|
||||||
|
"(formula: %s). Check that the lines used in the formula "
|
||||||
|
"really exists and have a lower sequence than the current "
|
||||||
|
"line.") % (line.sequence, line.python_code))
|
||||||
|
except SyntaxError:
|
||||||
|
raise UserError(_(
|
||||||
|
"Impossible to compute the formula of line with sequence %s "
|
||||||
|
"(formula: %s): the syntax of the formula is wrong.")
|
||||||
|
% (line.sequence, line.python_code))
|
||||||
|
|
||||||
|
def compute_lines(self, sequence2amount):
|
||||||
|
prec = self.company_id.currency_id.rounding
|
||||||
|
input_sequence2amount = sequence2amount.copy()
|
||||||
|
for line in self.line_ids.filtered(lambda x: x.type == 'input'):
|
||||||
|
if line.sequence not in sequence2amount:
|
||||||
|
raise UserError(_(
|
||||||
|
"You deleted a line in the wizard. This is not allowed: "
|
||||||
|
"you should either update the template or modify the "
|
||||||
|
"journal entry that will be generated by this wizard."))
|
||||||
|
input_sequence2amount.pop(line.sequence)
|
||||||
|
if input_sequence2amount:
|
||||||
|
raise UserError(_(
|
||||||
|
"You added a line in the wizard. This is not allowed: "
|
||||||
|
"you should either update the template or modify "
|
||||||
|
"the journal entry that will be generated by this wizard."))
|
||||||
|
for line in self.line_ids.filtered(lambda x: x.type == 'computed'):
|
||||||
|
self.eval_computed_line(line, sequence2amount)
|
||||||
|
sequence2amount[line.sequence] = float_round(
|
||||||
|
sequence2amount[line.sequence], precision_rounding=prec)
|
||||||
|
return sequence2amount
|
||||||
|
|
||||||
|
def generate_journal_entry(self):
|
||||||
|
'''Called by the button on the form view'''
|
||||||
|
self.ensure_one()
|
||||||
|
wiz = self.env['account.move.template.run'].create({
|
||||||
|
'template_id': self.id})
|
||||||
|
action = wiz.load_lines()
|
||||||
|
return action
|
||||||
|
|
||||||
|
|
||||||
class AccountMoveTemplateLine(models.Model):
|
class AccountMoveTemplateLine(models.Model):
|
||||||
_name = 'account.move.template.line'
|
_name = 'account.move.template.line'
|
||||||
_inherit = 'account.document.template.line'
|
_description = 'Journal Item Template'
|
||||||
|
_order = 'sequence, id'
|
||||||
|
|
||||||
company_id = fields.Many2one('res.company',
|
template_id = fields.Many2one(
|
||||||
related='template_id.company_id',
|
'account.move.template', string='Move Template', ondelete='cascade')
|
||||||
readonly=True)
|
name = fields.Char(string='Label')
|
||||||
journal_id = fields.Many2one('account.journal',
|
sequence = fields.Integer('Sequence', required=True)
|
||||||
related='template_id.journal_id',
|
|
||||||
store=True, readonly=True)
|
|
||||||
account_id = fields.Many2one(
|
account_id = fields.Many2one(
|
||||||
'account.account',
|
'account.account', string='Account',
|
||||||
required=True,
|
required=True, domain=[('deprecated', '=', False)])
|
||||||
ondelete="cascade"
|
partner_id = fields.Many2one(
|
||||||
)
|
'res.partner', string='Partner',
|
||||||
partner_id = fields.Many2one('res.partner', string='Partner')
|
domain=['|', ('parent_id', '=', False), ('is_company', '=', True)])
|
||||||
move_line_type = fields.Selection(
|
|
||||||
[('cr', 'Credit'), ('dr', 'Debit')],
|
|
||||||
required=True
|
|
||||||
)
|
|
||||||
analytic_account_id = fields.Many2one(
|
analytic_account_id = fields.Many2one(
|
||||||
'account.analytic.account',
|
'account.analytic.account', string='Analytic Account')
|
||||||
ondelete="cascade"
|
analytic_tag_ids = fields.Many2many(
|
||||||
)
|
'account.analytic.tag', string='Analytic Tags')
|
||||||
analytic_tag_ids = fields.Many2many('account.analytic.tag',
|
|
||||||
string='Analytic tags')
|
|
||||||
tax_ids = fields.Many2many('account.tax', string='Taxes')
|
tax_ids = fields.Many2many('account.tax', string='Taxes')
|
||||||
tax_line_id = fields.Many2one('account.tax', string='Originator tax',
|
tax_line_id = fields.Many2one(
|
||||||
ondelete='restrict')
|
'account.tax', string='Originator Tax', ondelete='restrict')
|
||||||
template_id = fields.Many2one('account.move.template')
|
company_id = fields.Many2one(
|
||||||
|
related='template_id.company_id', store=True)
|
||||||
|
company_currency_id = fields.Many2one(
|
||||||
|
related='template_id.company_id.currency_id',
|
||||||
|
string='Company Currency', store=True)
|
||||||
|
note = fields.Char()
|
||||||
|
type = fields.Selection([
|
||||||
|
('computed', 'Computed'),
|
||||||
|
('input', 'User input'),
|
||||||
|
], string='Type', required=True, default='input')
|
||||||
|
python_code = fields.Text('Python Code')
|
||||||
|
move_line_type = fields.Selection(
|
||||||
|
[('cr', 'Credit'), ('dr', 'Debit')], required=True, string='Direction')
|
||||||
|
|
||||||
_sql_constraints = [
|
_sql_constraints = [(
|
||||||
('sequence_template_uniq', 'unique (template_id,sequence)',
|
'sequence_template_uniq',
|
||||||
'The sequence of the line must be unique per template !')
|
'unique(template_id, sequence)',
|
||||||
]
|
'The sequence of the line must be unique per template!'
|
||||||
|
)]
|
||||||
|
|
||||||
|
@api.constrains('type', 'python_code')
|
||||||
|
def check_python_code(self):
|
||||||
|
for line in self:
|
||||||
|
if line.type == 'computed' and not line.python_code:
|
||||||
|
raise ValidationError(_(
|
||||||
|
"Python Code must be set for computed line with "
|
||||||
|
"sequence %d.") % line.sequence)
|
||||||
|
@ -5,6 +5,7 @@ Authors
|
|||||||
* Lorenzo Battistini <lorenzo.battistini@agilebg.com>
|
* Lorenzo Battistini <lorenzo.battistini@agilebg.com>
|
||||||
* Paolo Chiara <p.chiara@isa.it>
|
* Paolo Chiara <p.chiara@isa.it>
|
||||||
* Franco Tampieri <franco.tampieri@agilebg.com>
|
* Franco Tampieri <franco.tampieri@agilebg.com>
|
||||||
|
* Alexis de Lattre <alexis.delattre@akretion.com> (full re-write for v12)
|
||||||
|
|
||||||
Contributors
|
Contributors
|
||||||
------------
|
------------
|
||||||
@ -13,4 +14,4 @@ Contributors
|
|||||||
* Alex Comba <alex.comba@agilebg.com> (Port to V8)
|
* Alex Comba <alex.comba@agilebg.com> (Port to V8)
|
||||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||||
* Raf Ven <raf.ven@dynapps.be> (port to v11)
|
* Raf Ven <raf.ven@dynapps.be> (port to v11)
|
||||||
* Jordi Ballester <jordi.ballester@eficent.com> (EFICENT)
|
* Jordi Ballester <jordi.ballester@eficent.com> (EFICENT)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
To create new templates:
|
To create new templates:
|
||||||
|
|
||||||
#. Make sure that you have flagged *Show Full Accounting Features* in your
|
#. Make sure that you have flagged *Show Full Accounting Features* in your
|
||||||
user, and that the user has belongs to the *Billing Manager* group.
|
user, and that the user belongs to the *Billing Manager* group.
|
||||||
#. Go to *Invoicing / Configuration / Accounting / Journal Templates* and
|
#. Go to *Invoicing / Configuration / Accounting / Journal Templates* and
|
||||||
define there your template. You can choose to complete a line using a
|
define there your template. You can choose to complete a line using a
|
||||||
defined formula, based on other lines, or by requiring the user input.
|
defined formula, based on other lines, or by requiring the user input.
|
||||||
@ -10,4 +10,4 @@ To use an existing template:
|
|||||||
|
|
||||||
#. Go to *Invoicing / Adviser / Accounting Entries / Create Journal Entry from Template*
|
#. Go to *Invoicing / Adviser / Accounting Entries / Create Journal Entry from Template*
|
||||||
#. Select one of the available templates and optionally a partner.
|
#. Select one of the available templates and optionally a partner.
|
||||||
#. Complete the entries according to the template and press *Load*
|
#. Complete the entries according to the template and press *Load*
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
<odoo noupdate="1">
|
<odoo noupdate="1">
|
||||||
|
|
||||||
<record id="account_move_template_comp_rule" model="ir.rule">
|
<record id="account_move_template_comp_rule" model="ir.rule">
|
||||||
<field name="name">Move Template multi company rule</field>
|
<field name="name">Move Template multi-company rule</field>
|
||||||
<field name="model_id" ref="model_account_move_template"/>
|
<field name="model_id" ref="model_account_move_template"/>
|
||||||
<field name="global" eval="True"/>
|
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
"access_account_document_template_user","account_document_template_user","model_account_document_template","account.group_account_user","1","1","1","1"
|
access_account_move_template_user,Full access on account.move.template to accountant grp,model_account_move_template,account.group_account_user,1,1,1,1
|
||||||
"access_account_document_template_manager","account_document_template_manager","model_account_document_template","account.group_account_manager","1","1","1","1"
|
access_account_move_template_line_user,Full access on account.move.template.line to accountant grp,model_account_move_template_line,account.group_account_user,1,1,1,1
|
||||||
"access_account_document_template_line_user","account_document_template_line_user","model_account_document_template_line","account.group_account_user","1","1","1","1"
|
|
||||||
"access_account_document_template_line_manager","account_document_template_line_manager","model_account_document_template_line","account.group_account_manager","1","1","1","1"
|
|
||||||
"access_account_move_template_user","account_move_template_user","model_account_move_template","account.group_account_user","1","1","1","1"
|
|
||||||
"access_account_move_template_manager","account_move_template_manager","model_account_move_template","account.group_account_manager","1","1","1","1"
|
|
||||||
"access_account_move_template_line_user","account_move_template_line_user","model_account_move_template_line","account.group_account_user","1","1","1","1"
|
|
||||||
"access_account_move_template_line_manager","account_move_template_line_manager","model_account_move_template_line","account.group_account_manager","1","1","1","1"
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
|||||||
|
# Needs to be re-written because wizard.multi.charts.accounts
|
||||||
from . import test_account_move_template
|
# doesn't exist any more on v12
|
||||||
|
# from . import test_account_move_template
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2018-2019 Eficent Business and IT Consulting Services, S.L.
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
import logging
|
import logging
|
||||||
from psycopg2 import IntegrityError
|
from psycopg2 import IntegrityError
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="view_move_template_line_tree" model="ir.ui.view">
|
<record id="account_move_template_line_tree" model="ir.ui.view">
|
||||||
<field name="name">account.move.template.line.tree</field>
|
<field name="name">account.move.template.line.tree</field>
|
||||||
<field name="model">account.move.template.line</field>
|
<field name="model">account.move.template.line</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree>
|
<tree>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="name"/>
|
<field name="account_id" domain="[('company_id', '=', company_id)]"/>
|
||||||
<field name="journal_id" domain="[('company_id','=',company_id)]"/>
|
|
||||||
<field name="account_id" domain="[('company_id','=',company_id)]"/>
|
|
||||||
<field name="partner_id"/>
|
<field name="partner_id"/>
|
||||||
<field name="analytic_account_id" domain="[('company_id','=',company_id)]" groups="analytic.group_analytic_accounting"/>
|
<field name="name"/>
|
||||||
|
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
|
||||||
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_accounting"/>
|
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_accounting"/>
|
||||||
<field name="tax_line_id"/>
|
|
||||||
<field name="tax_ids" widget="many2many_tags"/>
|
|
||||||
<field name="type"/>
|
|
||||||
<field name="python_code"/>
|
|
||||||
<field name="move_line_type"/>
|
<field name="move_line_type"/>
|
||||||
|
<field name="type"/>
|
||||||
|
<field name="note"/>
|
||||||
|
<field name="tax_line_id" invisible="1"/>
|
||||||
|
<field name="tax_ids" widget="many2many_tags" options="{'no_create': True}"/>
|
||||||
<field name="company_id" invisible="1"/>
|
<field name="company_id" invisible="1"/>
|
||||||
|
<field name="company_currency_id" invisible="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_move_template_line_form" model="ir.ui.view">
|
<record id="account_move_template_line_form" model="ir.ui.view">
|
||||||
<field name="name">account.move.template.line.form</field>
|
<field name="name">account.move.template.line.form</field>
|
||||||
<field name="model">account.move.template.line</field>
|
<field name="model">account.move.template.line</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
@ -30,46 +30,52 @@
|
|||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="name"/>
|
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="journal_id" domain="[('company_id','=',company_id)]"/>
|
<field name="name"/>
|
||||||
<field name="account_id" domain="[('company_id','=',company_id)]"/>
|
<field name="account_id" domain="[('company_id', '=', company_id)]"/>
|
||||||
<field name="partner_id"/>
|
<field name="partner_id"/>
|
||||||
<field name="company_id" invisible="1"/>
|
<field name="company_id" invisible="1"/>
|
||||||
</group>
|
</group>
|
||||||
<group groups="analytic.group_analytic_accounting" string="Analytic">
|
<group groups="analytic.group_analytic_accounting" string="Analytic">
|
||||||
<field name="analytic_account_id" domain="[('company_id','=',company_id)]"/>
|
<field name="analytic_account_id" domain="[('company_id','=',company_id)]"/>
|
||||||
<field name="analytic_tag_ids" widget="many2many_tags"/>
|
<field name="analytic_tag_ids" widget="many2many_tags"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="type"/>
|
|
||||||
<field name="move_line_type"/>
|
<field name="move_line_type"/>
|
||||||
|
<field name="type"/>
|
||||||
|
<field name="note"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Taxes">
|
<group string="Taxes">
|
||||||
<field name="tax_line_id"/>
|
<field name="tax_line_id"/>
|
||||||
<field name="tax_ids" widget="many2many_tags"/>
|
<field name="tax_ids" widget="many2many_tags"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<label for="python_code" string="Python Code"
|
<group name="python_code" attrs="{'invisible': [('type', '!=', 'computed')]}" col="1" string="Compute Formula">
|
||||||
attrs="{'invisible': [('type', '!=', 'computed')]}" nolabel="1"/>
|
<div class="oe_account_help">
|
||||||
<field name="python_code" colspan="4" attrs="{'readonly': [('type', '!=', 'computed')]}" nolabel="1"/>
|
<p>You can refer to other lines using their sequence number e.g. <i>L1</i> for line with sequence = 1. Examples:</p>
|
||||||
<div class="oe_account_help">You can refer to other lines using their
|
<ul>
|
||||||
sequence number (e.g. 'L(1)' for first line).
|
<li>L1 * 0.2</li>
|
||||||
Examples of code: 'L(1) * 0.2'; 'L(2) - L(1)'; 'L(1)
|
<li>L2 - L1</li>
|
||||||
+ L(2) + L(3)'; '1250'</div>
|
<li>L1 + L2 + L3</li>
|
||||||
|
<li>1250</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<field name="python_code" nolabel="1" attrs="{'required': [('type', '=', 'computed')]}"/>
|
||||||
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_move_template_form" model="ir.ui.view">
|
<record id="account_move_template_form" model="ir.ui.view">
|
||||||
<field name="name">account.move.template.form</field>
|
<field name="name">account.move.template.form</field>
|
||||||
<field name="model">account.move.template</field>
|
<field name="model">account.move.template</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Journal Entry Template">
|
<form string="Journal Entry Template">
|
||||||
<header>
|
<header>
|
||||||
<button string="Test template"
|
<button string="Generate Journal Entry"
|
||||||
name="action_run_template"
|
name="generate_journal_entry"
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
type="object"/>
|
type="object"/>
|
||||||
</header>
|
</header>
|
||||||
@ -78,58 +84,58 @@
|
|||||||
<label for="name" class="oe_edit_only"/>
|
<label for="name" class="oe_edit_only"/>
|
||||||
<h1><field name="name"/></h1>
|
<h1><field name="name"/></h1>
|
||||||
</div>
|
</div>
|
||||||
<group>
|
<group name="main">
|
||||||
<field name="company_id" widget='selection' groups="base.group_multi_company"/>
|
<group name="main-left">
|
||||||
<field name="journal_id" widget='selection'/>
|
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||||
|
<field name="journal_id" options="{'no_open': True, 'no_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<group name="main-right">
|
||||||
|
<field name="ref"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group name="lines">
|
||||||
|
<field name="line_ids" nolabel="1" context="{'default_company_id': company_id}"/>
|
||||||
</group>
|
</group>
|
||||||
<field nolabel="1" name="template_line_ids" context="{'default_company_id' : company_id}"/>
|
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
|
||||||
<field name="message_follower_ids" widget="mail_followers"/>
|
|
||||||
<!--<field name="activity_ids"
|
|
||||||
widget="mail_activity"/> TODO: uncomment on saas-15-->
|
|
||||||
<field name="message_ids" widget="mail_thread"/>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_move_template_tree" model="ir.ui.view">
|
<record id="account_move_template_tree" model="ir.ui.view">
|
||||||
<field name="name">account.move.template.tree</field>
|
<field name="name">account.move.template.tree</field>
|
||||||
<field name="model">account.move.template</field>
|
<field name="model">account.move.template</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
|
<field name="journal_id"/>
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field name="company_id" groups="base.group_multi_company"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_move_template_search" model="ir.ui.view">
|
<record id="account_move_template_search" model="ir.ui.view">
|
||||||
<field name="name">account.move.template.search</field>
|
<field name="name">account.move.template.search</field>
|
||||||
<field name="model">account.move.template</field>
|
<field name="model">account.move.template</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="Journal Entry Template">
|
<search string="Journal Entry Template">
|
||||||
<group>
|
<field name="name"/>
|
||||||
<separator orientation="vertical"/>
|
<group name="groupby">
|
||||||
<field name="name"/>
|
<filter name="journal_groupby" string="Journal" context="{'group_by': 'journal_id'}"/>
|
||||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_move_template_form" model="ir.actions.act_window">
|
<record id="account_move_template_action" model="ir.actions.act_window">
|
||||||
<field name="name">Journal Entry Templates</field>
|
<field name="name">Journal Entry Templates</field>
|
||||||
<field name="res_model">account.move.template</field>
|
<field name="res_model">account.move.template</field>
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="search_view_id" ref="view_move_template_search"/>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
action="action_move_template_form"
|
id="account_move_template_menu"
|
||||||
id="menu_action_move_template_form" sequence="300"
|
action="account_move_template_action"
|
||||||
parent="account.account_account_menu"
|
parent="account.account_account_menu"
|
||||||
groups="account.group_account_manager"/>
|
sequence="300"/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
@ -1 +1 @@
|
|||||||
from . import select_template
|
from . import account_move_template_run
|
||||||
|
166
account_move_template/wizard/account_move_template_run.py
Normal file
166
account_move_template/wizard/account_move_template_run.py
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
# Copyright 2015-2019 See manifest
|
||||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
|
from odoo import fields, models, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tools import float_is_zero
|
||||||
|
|
||||||
|
|
||||||
|
class AccountMoveTemplateRun(models.TransientModel):
|
||||||
|
_name = "account.move.template.run"
|
||||||
|
_description = "Wizard to generate move from template"
|
||||||
|
|
||||||
|
template_id = fields.Many2one('account.move.template', required=True)
|
||||||
|
company_id = fields.Many2one(
|
||||||
|
'res.company', required=True, readonly=True,
|
||||||
|
default=lambda self: self.env['res.company']._company_default_get())
|
||||||
|
partner_id = fields.Many2one(
|
||||||
|
'res.partner', 'Override Partner',
|
||||||
|
domain=['|', ('parent_id', '=', False), ('is_company', '=', True)])
|
||||||
|
date = fields.Date(required=True, default=fields.Date.context_today)
|
||||||
|
journal_id = fields.Many2one(
|
||||||
|
'account.journal', string='Journal', readonly=True)
|
||||||
|
ref = fields.Char(string='Reference')
|
||||||
|
line_ids = fields.One2many(
|
||||||
|
'account.move.template.line.run', 'wizard_id', string="Lines")
|
||||||
|
state = fields.Selection([
|
||||||
|
('select_template', 'Select Template'),
|
||||||
|
('set_lines', 'Set Lines'),
|
||||||
|
], readonly=True, default='select_template')
|
||||||
|
|
||||||
|
def _prepare_wizard_line(self, line):
|
||||||
|
vals = {
|
||||||
|
'wizard_id': self.id,
|
||||||
|
'sequence': line.sequence,
|
||||||
|
'name': line.name,
|
||||||
|
'amount': 0.0,
|
||||||
|
'account_id': line.account_id.id,
|
||||||
|
'partner_id': line.partner_id.id or False,
|
||||||
|
'move_line_type': line.move_line_type,
|
||||||
|
'tax_ids': [(6, 0, line.tax_ids.ids)],
|
||||||
|
'tax_line_id': line.tax_line_id.id,
|
||||||
|
'analytic_account_id': line.analytic_account_id.id,
|
||||||
|
'analytic_tag_ids': [(6, 0, line.analytic_tag_ids.ids)],
|
||||||
|
'note': line.note,
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
|
||||||
|
# STEP 1
|
||||||
|
def load_lines(self):
|
||||||
|
self.ensure_one()
|
||||||
|
amtlro = self.env['account.move.template.line.run']
|
||||||
|
if self.company_id != self.template_id.company_id:
|
||||||
|
raise UserError(_(
|
||||||
|
"The selected template (%s) is not in the same company (%s) "
|
||||||
|
"as the current user (%s).") % (
|
||||||
|
self.template_id.name,
|
||||||
|
self.template_id.company_id.display_name,
|
||||||
|
self.company_id.display_name))
|
||||||
|
lines = self.template_id.line_ids
|
||||||
|
for line in lines.filtered(lambda l: l.type == 'input'):
|
||||||
|
vals = self._prepare_wizard_line(line)
|
||||||
|
amtlro.create(vals)
|
||||||
|
self.write({
|
||||||
|
'journal_id': self.template_id.journal_id.id,
|
||||||
|
'state': 'set_lines',
|
||||||
|
})
|
||||||
|
if not self.line_ids:
|
||||||
|
return self.generate_move()
|
||||||
|
action = self.env.ref(
|
||||||
|
'account_move_template.account_move_template_run_action')
|
||||||
|
result = action.read()[0]
|
||||||
|
result.update({
|
||||||
|
'res_id': self.id,
|
||||||
|
'context': self.env.context,
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
# STEP 2
|
||||||
|
def generate_move(self):
|
||||||
|
self.ensure_one()
|
||||||
|
sequence2amount = {}
|
||||||
|
for wizard_line in self.line_ids:
|
||||||
|
sequence2amount[wizard_line.sequence] = wizard_line.amount
|
||||||
|
prec = self.company_id.currency_id.rounding
|
||||||
|
if all([
|
||||||
|
float_is_zero(x, precision_rounding=prec)
|
||||||
|
for x in sequence2amount.values()]):
|
||||||
|
raise UserError(_("Debit and credit of all lines are null."))
|
||||||
|
self.template_id.compute_lines(sequence2amount)
|
||||||
|
move_vals = self._prepare_move()
|
||||||
|
for line in self.template_id.line_ids:
|
||||||
|
amount = sequence2amount[line.sequence]
|
||||||
|
if not float_is_zero(amount, precision_rounding=prec):
|
||||||
|
move_vals['line_ids'].append(
|
||||||
|
(0, 0, self._prepare_move_line(line, amount)))
|
||||||
|
move = self.env['account.move'].create(move_vals)
|
||||||
|
action = self.env.ref('account.action_move_journal_line')
|
||||||
|
result = action.read()[0]
|
||||||
|
result.update({
|
||||||
|
'name': _('Entry from template %s') % self.template_id.name,
|
||||||
|
'res_id': move.id,
|
||||||
|
'views': False,
|
||||||
|
'view_id': False,
|
||||||
|
'view_mode': 'form,tree,kanban',
|
||||||
|
'context': self.env.context,
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _prepare_move(self):
|
||||||
|
move_vals = {
|
||||||
|
'ref': self.ref,
|
||||||
|
'journal_id': self.journal_id.id,
|
||||||
|
'date': self.date,
|
||||||
|
'company_id': self.company_id.id,
|
||||||
|
'line_ids': [],
|
||||||
|
}
|
||||||
|
return move_vals
|
||||||
|
|
||||||
|
def _prepare_move_line(self, line, amount):
|
||||||
|
debit = line.move_line_type == 'dr'
|
||||||
|
values = {
|
||||||
|
'name': line.name,
|
||||||
|
'analytic_account_id': line.analytic_account_id.id,
|
||||||
|
'account_id': line.account_id.id,
|
||||||
|
'credit': not debit and amount or 0.0,
|
||||||
|
'debit': debit and amount or 0.0,
|
||||||
|
'partner_id': self.partner_id.id or line.partner_id.id,
|
||||||
|
'tax_line_id': line.tax_line_id.id,
|
||||||
|
}
|
||||||
|
if line.analytic_tag_ids:
|
||||||
|
values['analytic_tag_ids'] = [(6, 0, line.analytic_tag_ids.ids)]
|
||||||
|
if line.tax_ids:
|
||||||
|
values['tax_ids'] = [(6, 0, line.tax_ids.ids)]
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
class AccountMoveTemplateLineRun(models.TransientModel):
|
||||||
|
_name = "account.move.template.line.run"
|
||||||
|
_description = 'Wizard Lines to generate move from template'
|
||||||
|
|
||||||
|
wizard_id = fields.Many2one(
|
||||||
|
'account.move.template.run', ondelete='cascade')
|
||||||
|
company_id = fields.Many2one(
|
||||||
|
related='wizard_id.company_id')
|
||||||
|
company_currency_id = fields.Many2one(
|
||||||
|
related='wizard_id.company_id.currency_id', string='Company Currency')
|
||||||
|
sequence = fields.Integer('Sequence', required=True)
|
||||||
|
name = fields.Char('Name')
|
||||||
|
account_id = fields.Many2one(
|
||||||
|
'account.account', required=True, readonly=True)
|
||||||
|
analytic_account_id = fields.Many2one(
|
||||||
|
'account.analytic.account', readonly=True)
|
||||||
|
analytic_tag_ids = fields.Many2many(
|
||||||
|
'account.analytic.tag', string='Analytic Tags', readonly=True)
|
||||||
|
tax_ids = fields.Many2many('account.tax', string='Taxes', readonly=True)
|
||||||
|
tax_line_id = fields.Many2one(
|
||||||
|
'account.tax', string='Originator Tax',
|
||||||
|
ondelete='restrict', readonly=True)
|
||||||
|
partner_id = fields.Many2one(
|
||||||
|
'res.partner', readonly=True, string='Partner')
|
||||||
|
move_line_type = fields.Selection(
|
||||||
|
[('cr', 'Credit'), ('dr', 'Debit')],
|
||||||
|
required=True, readonly=True, string='Direction')
|
||||||
|
amount = fields.Monetary(
|
||||||
|
'Amount', required=True, currency_field='company_currency_id')
|
||||||
|
note = fields.Char(readonly=True)
|
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="account_move_template_run_form" model="ir.ui.view">
|
||||||
|
<field name="model">account.move.template.run</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Journal Entry Template" >
|
||||||
|
<group name="main">
|
||||||
|
<field name="state" invisible="1"/>
|
||||||
|
<field name="template_id" widget="selection"
|
||||||
|
domain="[('company_id', '=', company_id)]"
|
||||||
|
attrs="{'readonly': [('state', '=', 'set_lines')]}" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company"/>
|
||||||
|
<field name="date" states="set_lines"/>
|
||||||
|
<field name="journal_id" states="set_lines"/>
|
||||||
|
<field name="ref" states="set_lines"/>
|
||||||
|
<field name="partner_id" states="set_lines"/>
|
||||||
|
</group>
|
||||||
|
<group name="lines" states="set_lines">
|
||||||
|
<field name="line_ids" nolabel="1">
|
||||||
|
<tree editable="bottom">
|
||||||
|
<field name="sequence" invisible="1"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="account_id" domain="[('company_id','=',company_id)]"/>
|
||||||
|
<field name="partner_id"/>
|
||||||
|
<field name="analytic_account_id" domain="[('company_id','=',company_id)]" groups="analytic.group_analytic_accounting"/>
|
||||||
|
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_accounting"/>
|
||||||
|
<field name="tax_line_id" attrs="{'invisible': [('tax_line_id','=',False)]}"/>
|
||||||
|
<field name="tax_ids" widget="many2many_tags" attrs="{'invisible': [('tax_ids','=',[])]}"/>
|
||||||
|
<field name="move_line_type" />
|
||||||
|
<field name="amount" />
|
||||||
|
<field name="note"/>
|
||||||
|
<field name="company_id" invisible="1"/>
|
||||||
|
<field name="company_currency_id" invisible="1"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="load_lines" class="btn-primary" string="Next" type="object" states="select_template" />
|
||||||
|
<button name="generate_move" class="btn-primary" string="Create Journal Entry" type="object" states="set_lines" />
|
||||||
|
<button special="cancel" string="Cancel" class="btn-default"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="account_move_template_run_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Create Entry from Template</field>
|
||||||
|
<field name="res_model">account.move.template.run</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="account_move_template_run_menu"
|
||||||
|
parent="account.menu_finance_entries_accounting_entries"
|
||||||
|
action="account_move_template_run_action"
|
||||||
|
sequence="10"/>
|
||||||
|
</odoo>
|
@ -1,142 +0,0 @@
|
|||||||
# Copyright 2015-2017 See manifest
|
|
||||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
|
|
||||||
from odoo import models, fields, api, _
|
|
||||||
|
|
||||||
|
|
||||||
class WizardSelectMoveTemplate(models.TransientModel):
|
|
||||||
_name = "wizard.select.move.template"
|
|
||||||
|
|
||||||
template_id = fields.Many2one('account.move.template', required=True)
|
|
||||||
company_id = fields.Many2one(
|
|
||||||
'res.company', required=True,
|
|
||||||
default=lambda self: self.env.user.company_id)
|
|
||||||
partner_id = fields.Many2one('res.partner', 'Partner')
|
|
||||||
date = fields.Date(required=True, default=fields.Date.context_today)
|
|
||||||
line_ids = fields.One2many(
|
|
||||||
'wizard.select.move.template.line', 'template_id')
|
|
||||||
state = fields.Selection(
|
|
||||||
[('template_selected', 'Template selected')])
|
|
||||||
|
|
||||||
@api.onchange('template_id', 'company_id')
|
|
||||||
def onchange_company_id(self):
|
|
||||||
template_domain = [('company_id', '=', self.company_id.id)]
|
|
||||||
return {'domain': {'template_id': template_domain}}
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def load_lines(self):
|
|
||||||
self.ensure_one()
|
|
||||||
lines = self.template_id.template_line_ids
|
|
||||||
for line in lines.filtered(lambda l: l.type == 'input'):
|
|
||||||
self.env['wizard.select.move.template.line'].create({
|
|
||||||
'template_id': self.id,
|
|
||||||
'sequence': line.sequence,
|
|
||||||
'name': line.name,
|
|
||||||
'amount': 0.0,
|
|
||||||
'account_id': line.account_id.id,
|
|
||||||
'partner_id': line.partner_id.id or self.partner_id.id,
|
|
||||||
'move_line_type': line.move_line_type,
|
|
||||||
'tax_ids': [(6, 0, line.tax_ids.ids)],
|
|
||||||
'tax_line_id': line.tax_line_id.id,
|
|
||||||
'analytic_account_id': line.analytic_account_id.id,
|
|
||||||
'analytic_tag_ids': [(6, 0, line.analytic_tag_ids.ids)],
|
|
||||||
})
|
|
||||||
if not self.line_ids:
|
|
||||||
return self.load_template()
|
|
||||||
self.state = 'template_selected'
|
|
||||||
view_rec = self.env.ref('account_move_template.wizard_select_template')
|
|
||||||
action = self.env.ref(
|
|
||||||
'account_move_template.action_wizard_select_template_by_move')
|
|
||||||
result = action.read()[0]
|
|
||||||
result['res_id'] = self.id
|
|
||||||
result['view_id'] = [view_rec.id]
|
|
||||||
result['context'] = self.env.context
|
|
||||||
return result
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def load_template(self):
|
|
||||||
self.ensure_one()
|
|
||||||
input_lines = {}
|
|
||||||
for template_line in self.line_ids:
|
|
||||||
input_lines[template_line.sequence] = template_line.amount
|
|
||||||
amounts = self.template_id.compute_lines(input_lines)
|
|
||||||
name = self.template_id.name
|
|
||||||
partner = self.partner_id.id
|
|
||||||
moves = self.env['account.move']
|
|
||||||
for journal in self.template_id.template_line_ids.mapped('journal_id'):
|
|
||||||
lines = []
|
|
||||||
move = self._create_move(name, journal.id)
|
|
||||||
moves = moves + move
|
|
||||||
for line in self.template_id.template_line_ids.filtered(
|
|
||||||
lambda l, j=journal: l.journal_id == j):
|
|
||||||
lines.append((0, 0,
|
|
||||||
self._prepare_line(line, amounts, partner)))
|
|
||||||
move.write({'line_ids': lines})
|
|
||||||
action = self.env.ref('account.action_move_journal_line')
|
|
||||||
result = action.read()[0]
|
|
||||||
result['domain'] = [('id', 'in', moves.ids)]
|
|
||||||
result['name'] = _('Entries from template: %s') % name
|
|
||||||
result['context'] = self.env.context
|
|
||||||
return result
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _create_move(self, ref, journal_id):
|
|
||||||
return self.env['account.move'].create({
|
|
||||||
'ref': ref,
|
|
||||||
'journal_id': journal_id,
|
|
||||||
'date': self.date,
|
|
||||||
})
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _prepare_line(self, line, amounts, partner_id):
|
|
||||||
debit = line.move_line_type == 'dr'
|
|
||||||
values = {
|
|
||||||
'name': line.name,
|
|
||||||
'journal_id': line.journal_id.id,
|
|
||||||
'analytic_account_id': line.analytic_account_id.id,
|
|
||||||
'account_id': line.account_id.id,
|
|
||||||
'credit': not debit and amounts[line.sequence] or 0.0,
|
|
||||||
'debit': debit and amounts[line.sequence] or 0.0,
|
|
||||||
'partner_id': line.partner_id.id or partner_id,
|
|
||||||
'tax_line_id': line.tax_line_id.id,
|
|
||||||
}
|
|
||||||
if line.analytic_tag_ids:
|
|
||||||
values['analytic_tag_ids'] = [(6, 0, line.analytic_tag_ids.ids)]
|
|
||||||
if line.tax_ids:
|
|
||||||
values['tax_ids'] = [(6, 0, line.tax_ids.ids)]
|
|
||||||
return values
|
|
||||||
|
|
||||||
|
|
||||||
class WizardSelectMoveTemplateLine(models.TransientModel):
|
|
||||||
_description = 'Template Lines'
|
|
||||||
_name = "wizard.select.move.template.line"
|
|
||||||
|
|
||||||
template_id = fields.Many2one(
|
|
||||||
'wizard.select.move.template')
|
|
||||||
company_id = fields.Many2one('res.company',
|
|
||||||
related='template_id.company_id',
|
|
||||||
readonly=True)
|
|
||||||
sequence = fields.Integer('Sequence', required=True,
|
|
||||||
)
|
|
||||||
name = fields.Char('Name', required=True, readonly=True,
|
|
||||||
)
|
|
||||||
account_id = fields.Many2one(
|
|
||||||
'account.account', required=True, readonly=True)
|
|
||||||
analytic_account_id = fields.Many2one(
|
|
||||||
'account.analytic.account',
|
|
||||||
ondelete="cascade", readonly=True,
|
|
||||||
)
|
|
||||||
analytic_tag_ids = fields.Many2many('account.analytic.tag',
|
|
||||||
string='Analytic tags',
|
|
||||||
readonly=True,)
|
|
||||||
tax_ids = fields.Many2many('account.tax', string='Taxes', readonly=True)
|
|
||||||
tax_line_id = fields.Many2one('account.tax', string='Originator tax',
|
|
||||||
ondelete='restrict', readonly=True)
|
|
||||||
partner_id = fields.Many2one('res.partner', readonly=True,
|
|
||||||
string='Partner')
|
|
||||||
move_line_type = fields.Selection([('cr', 'Credit'), ('dr', 'Debit')],
|
|
||||||
required=True, readonly=True,
|
|
||||||
string='Journal Item Type',
|
|
||||||
)
|
|
||||||
amount = fields.Float('Amount', required=True,
|
|
||||||
)
|
|
@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<record id="wizard_select_template" model="ir.ui.view">
|
|
||||||
<field name="name">Select Journal Entry Template</field>
|
|
||||||
<field name="model">wizard.select.move.template</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="Journal Entry Template" >
|
|
||||||
<field name="state" invisible="1"/>
|
|
||||||
<group>
|
|
||||||
<group>
|
|
||||||
<field name="template_id" widget="selection"
|
|
||||||
attrs="{'invisible':[('state','=','template_selected')]}"
|
|
||||||
domain="[('company_id','=',company_id)]"/>
|
|
||||||
</group>
|
|
||||||
<group>
|
|
||||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
|
||||||
<field name="partner_id" attrs="{'invisible':[('state','=','template_selected')]}"/>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
<separator
|
|
||||||
string="Modify the lines before create them or edit them after creation."
|
|
||||||
attrs="{'invisible':[('state','!=','template_selected')]}"/>
|
|
||||||
<field name="line_ids" nolabel="1" attrs="{'invisible':[('state','!=','template_selected')]}"/>
|
|
||||||
<footer>
|
|
||||||
<button name="load_template" class="btn-primary" string="Load" type="object" colspan="1" attrs="{'invisible':[('state','!=','template_selected')]}" />
|
|
||||||
<button name="load_lines" class="btn-primary" string="Next" type="object" attrs="{'invisible':[('state','=','template_selected')]}" />
|
|
||||||
<button special="cancel" string="Cancel" class="btn-default"/>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="wizard_select_template_line" model="ir.ui.view">
|
|
||||||
<field name="name">Select Journal Entry Template Line</field>
|
|
||||||
<field name="model">wizard.select.move.template.line</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="Journal Entry Template Line">
|
|
||||||
<group>
|
|
||||||
<field name="sequence" invisible="1"/>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="account_id" domain="[('company_id','=',company_id)]"/>
|
|
||||||
<field name="partner_id"/>
|
|
||||||
<field name="analytic_account_id" domain="[('company_id','=',company_id)]" groups="analytic.group_analytic_accounting"/>
|
|
||||||
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_accounting"/>
|
|
||||||
<field name="tax_line_id" attrs="{'invisible': [('tax_line_id','=',False)]}"/>
|
|
||||||
<field name="tax_ids" widget="many2many_tags" attrs="{'invisible': [('tax_ids','=',[])]}"/>
|
|
||||||
<field name="move_line_type"/>
|
|
||||||
<field name="amount"/>
|
|
||||||
<field name="company_id" invisible="1"/>
|
|
||||||
</group>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="wizard_select_template_line_tree" model="ir.ui.view">
|
|
||||||
<field name="name">Select Journal Entry Template Line</field>
|
|
||||||
<field name="model">wizard.select.move.template.line</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree editable="bottom">
|
|
||||||
<field name="sequence" invisible="1"/>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="account_id" domain="[('company_id','=',company_id)]"/>
|
|
||||||
<field name="partner_id"/>
|
|
||||||
<field name="analytic_account_id" domain="[('company_id','=',company_id)]" groups="analytic.group_analytic_accounting"/>
|
|
||||||
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_accounting"/>
|
|
||||||
<field name="tax_line_id" attrs="{'invisible': [('tax_line_id','=',False)]}"/>
|
|
||||||
<field name="tax_ids" widget="many2many_tags" attrs="{'invisible': [('tax_ids','=',[])]}"/>
|
|
||||||
<field name="move_line_type" />
|
|
||||||
<field name="amount" />
|
|
||||||
<field name="company_id" invisible="1"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_wizard_select_template" model="ir.actions.act_window">
|
|
||||||
<field name="name">Select Journal Entry Template</field>
|
|
||||||
<field name="res_model">wizard.select.move.template</field>
|
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_mode">form</field>
|
|
||||||
<field name="view_id" ref="wizard_select_template"/>
|
|
||||||
<field name="target">new</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<act_window name="Create Journal Entry from Template"
|
|
||||||
res_model="wizard.select.move.template"
|
|
||||||
src_model="account.move"
|
|
||||||
view_mode="form"
|
|
||||||
target="new"
|
|
||||||
key2="client_action_multi"
|
|
||||||
id="action_wizard_select_template_by_move"
|
|
||||||
view_id="wizard_select_template"/>
|
|
||||||
|
|
||||||
<menuitem name="Create Journal Entry from Template" action="action_wizard_select_template" id="menu_action_wizard_select_template" sequence="10" parent="account.menu_finance_entries_accounting_entries"/>
|
|
||||||
</odoo>
|
|
Loading…
Reference in New Issue
Block a user