mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[IMP] account_invoice_change,account_invoice_change_analytic: change multiple invoices
H12964
This commit is contained in:
@@ -23,6 +23,7 @@ the invoice is currently in.
|
|||||||
'account',
|
'account',
|
||||||
],
|
],
|
||||||
'data': [
|
'data': [
|
||||||
|
'data/server_actions.xml',
|
||||||
'wizard/invoice_change_views.xml',
|
'wizard/invoice_change_views.xml',
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
|
|||||||
23
account_invoice_change/data/server_actions.xml
Normal file
23
account_invoice_change/data/server_actions.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<record model="ir.actions.server" id="action_invoice_change">
|
||||||
|
<field name="name">Change Invoice</field>
|
||||||
|
<field name="model_id" ref="account.model_account_move"/>
|
||||||
|
<field name="binding_model_id" ref="account.model_account_move" />
|
||||||
|
<field name="binding_view_types">list</field>
|
||||||
|
<field name="state">code</field>
|
||||||
|
<field name="groups_id" eval="[(4,ref('account.group_account_manager'))]"/>
|
||||||
|
<field name="code">
|
||||||
|
if records:
|
||||||
|
action = env['ir.actions.act_window'].for_xml_id('account_invoice_change', 'action_view_account_invoice_change')
|
||||||
|
action['context'] = {
|
||||||
|
'active_model': model._name,
|
||||||
|
'active_ids': records.ids,
|
||||||
|
}
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
from odoo import fields
|
from odoo import fields
|
||||||
from odoo.tests import tagged
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tests import tagged, Form
|
||||||
from odoo.addons.account.tests.account_test_users import AccountTestUsers
|
from odoo.addons.account.tests.account_test_users import AccountTestUsers
|
||||||
|
|
||||||
|
|
||||||
@@ -55,3 +56,65 @@ class TestInvoiceChange(InvoiceChangeCommon):
|
|||||||
self.assertEqual(str(self.invoice_basic.invoice_date), change_invoice_date)
|
self.assertEqual(str(self.invoice_basic.invoice_date), change_invoice_date)
|
||||||
self.assertEqual(self.invoice_basic.invoice_user_id, change_user)
|
self.assertEqual(self.invoice_basic.invoice_user_id, change_user)
|
||||||
self.assertEqual(str(self.invoice_basic.line_ids[0].date), change_date)
|
self.assertEqual(str(self.invoice_basic.line_ids[0].date), change_date)
|
||||||
|
|
||||||
|
def _create_journal_entry(self):
|
||||||
|
revenue_account = self.env['account.account'].search([
|
||||||
|
('company_id', '=', self.main_company.id),
|
||||||
|
('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)
|
||||||
|
], limit=1)
|
||||||
|
expense_account = self.env['account.account'].search([
|
||||||
|
('company_id', '=', self.main_company.id),
|
||||||
|
('user_type_id', '=', self.env.ref('account.data_account_type_expenses').id)
|
||||||
|
], limit=1)
|
||||||
|
return self.env['account.move'].create({
|
||||||
|
'type': 'entry',
|
||||||
|
'date': '2019-01-01',
|
||||||
|
'line_ids': [
|
||||||
|
(0, 0, {
|
||||||
|
'name': 'line_debit',
|
||||||
|
'account_id': revenue_account.id,
|
||||||
|
}),
|
||||||
|
(0, 0, {
|
||||||
|
'name': 'line_credit',
|
||||||
|
'account_id': expense_account.id,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_invoice_change_multiple(self):
|
||||||
|
journal_entry = self._create_journal_entry()
|
||||||
|
ctx = {'active_model': 'account.move', 'active_ids': [self.invoice_basic.id, journal_entry.id]}
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
change = Form(self.env['account.invoice.change'].with_context(ctx))
|
||||||
|
|
||||||
|
other_invoice = self.invoice_basic.copy()
|
||||||
|
ctx = {'active_model': 'account.move', 'active_ids': [self.invoice_basic.id, other_invoice.id]}
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
change = Form(self.env['account.invoice.change'].with_context(ctx))
|
||||||
|
|
||||||
|
self.invoice_basic.action_post()
|
||||||
|
other_invoice.action_post()
|
||||||
|
change = Form(self.env['account.invoice.change'].with_context(ctx))
|
||||||
|
self.assertFalse(change.date)
|
||||||
|
self.assertFalse(change.invoice_date)
|
||||||
|
self.assertFalse(change.invoice_user_id)
|
||||||
|
|
||||||
|
change_date = '2018-01-01'
|
||||||
|
change_invoice_date = '2019-01-01'
|
||||||
|
change_user = self.env.user
|
||||||
|
change.set_invoice_user_id = True
|
||||||
|
change.set_date = True
|
||||||
|
change.set_invoice_date = True
|
||||||
|
change.invoice_user_id = change_user
|
||||||
|
change.date = change_date
|
||||||
|
change.invoice_date = change_invoice_date
|
||||||
|
|
||||||
|
change.save().affect_change()
|
||||||
|
self.assertEqual(str(self.invoice_basic.date), change_date)
|
||||||
|
self.assertEqual(str(self.invoice_basic.invoice_date), change_invoice_date)
|
||||||
|
self.assertEqual(self.invoice_basic.invoice_user_id, change_user)
|
||||||
|
self.assertEqual(str(self.invoice_basic.line_ids[0].date), change_date)
|
||||||
|
self.assertEqual(str(other_invoice.date), change_date)
|
||||||
|
self.assertEqual(str(other_invoice.invoice_date), change_invoice_date)
|
||||||
|
self.assertEqual(other_invoice.invoice_user_id, change_user)
|
||||||
|
self.assertEqual(str(other_invoice.line_ids[0].date), change_date)
|
||||||
|
|||||||
@@ -6,11 +6,15 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
_name = 'account.invoice.change'
|
_name = 'account.invoice.change'
|
||||||
_description = 'Invoice Change'
|
_description = 'Invoice Change'
|
||||||
|
|
||||||
move_id = fields.Many2one('account.move', string='Invoice', readonly=True, required=True)
|
move_ids = fields.Many2many('account.move', string='Invoice', readonly=True, required=True)
|
||||||
move_company_id = fields.Many2one('res.company', readonly=True, related='move_id.company_id')
|
is_single_move = fields.Boolean(compute='_compute_move_company_id')
|
||||||
|
move_company_id = fields.Many2one('res.company', readonly=True, compute='_compute_move_company_id')
|
||||||
invoice_user_id = fields.Many2one('res.users', string='Salesperson')
|
invoice_user_id = fields.Many2one('res.users', string='Salesperson')
|
||||||
|
set_invoice_user_id = fields.Boolean()
|
||||||
date = fields.Date(string='Accounting Date')
|
date = fields.Date(string='Accounting Date')
|
||||||
|
set_date = fields.Boolean()
|
||||||
invoice_date = fields.Date(string='Invoice Date')
|
invoice_date = fields.Date(string='Invoice Date')
|
||||||
|
set_invoice_date = fields.Boolean()
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def default_get(self, fields):
|
def default_get(self, fields):
|
||||||
@@ -28,24 +32,40 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
"Programmation error: the expected model for this action is 'account.move'. The provided one is '%d'.") % active_model)
|
"Programmation error: the expected model for this action is 'account.move'. The provided one is '%d'.") % active_model)
|
||||||
|
|
||||||
# Checks on received invoice records
|
# Checks on received invoice records
|
||||||
invoice = self.env[active_model].browse(active_ids)
|
invoices = self.env[active_model].browse(active_ids)
|
||||||
if len(invoice) != 1:
|
if invoices.filtered(lambda i: not i.is_invoice()):
|
||||||
raise UserError(_("Invoice Change expects only one invoice."))
|
raise UserError(_('Only invoices can be updated.'))
|
||||||
rec.update({
|
if invoices.filtered(lambda i: i.state in ('draft', 'cancel')):
|
||||||
'move_id': invoice.id,
|
raise UserError(_('Only posted invoices can be updated.'))
|
||||||
'invoice_user_id': invoice.invoice_user_id.id,
|
if len(invoices.company_id) > 1:
|
||||||
'date': invoice.date,
|
raise UserError(_('Selected invoices must be in the same company.'))
|
||||||
'invoice_date': invoice.invoice_date,
|
rec['move_ids'] = [(6, 0, invoices.ids)]
|
||||||
})
|
if len(invoices) == 1:
|
||||||
|
rec.update({
|
||||||
|
'set_invoice_user_id': True,
|
||||||
|
'set_date': True,
|
||||||
|
'set_invoice_date': True,
|
||||||
|
'invoice_user_id': invoices.invoice_user_id.id,
|
||||||
|
'date': invoices.date,
|
||||||
|
'invoice_date': invoices.invoice_date,
|
||||||
|
})
|
||||||
return rec
|
return rec
|
||||||
|
|
||||||
|
@api.depends('move_ids')
|
||||||
|
def _compute_move_company_id(self):
|
||||||
|
for wiz in self:
|
||||||
|
company = wiz.move_ids.company_id
|
||||||
|
company.ensure_one()
|
||||||
|
wiz.move_company_id = company
|
||||||
|
wiz.is_single_move = len(wiz.move_ids) == 1
|
||||||
|
|
||||||
def _new_move_vals(self):
|
def _new_move_vals(self):
|
||||||
vals = {}
|
vals = {}
|
||||||
if self.move_id.invoice_user_id != self.invoice_user_id:
|
if self.set_invoice_user_id:
|
||||||
vals['invoice_user_id'] = self.invoice_user_id.id
|
vals['invoice_user_id'] = self.invoice_user_id.id
|
||||||
if self.move_id.date != self.date:
|
if self.set_date:
|
||||||
vals['date'] = self.date
|
vals['date'] = self.date
|
||||||
if self.move_id.invoice_date != self.invoice_date:
|
if self.set_invoice_date:
|
||||||
vals['invoice_date'] = self.invoice_date
|
vals['invoice_date'] = self.invoice_date
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
@@ -53,5 +73,5 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
vals = self._new_move_vals()
|
vals = self._new_move_vals()
|
||||||
if vals:
|
if vals:
|
||||||
self.move_id.write(vals)
|
self.move_ids.write(vals)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -7,11 +7,15 @@
|
|||||||
<form string="Invoice Change">
|
<form string="Invoice Change">
|
||||||
<group>
|
<group>
|
||||||
<group name="group_left">
|
<group name="group_left">
|
||||||
<field name="move_id" invisible="1"/>
|
<field name="move_ids" invisible="1"/>
|
||||||
|
<field name="is_single_move" invisible="1"/>
|
||||||
<field name="move_company_id" invisible="1"/>
|
<field name="move_company_id" invisible="1"/>
|
||||||
<field name="invoice_user_id"/>
|
<field name="set_invoice_user_id" attrs="{'invisible': [('is_single_move', '=', True)]}"/>
|
||||||
<field name="invoice_date"/>
|
<field name="invoice_user_id" attrs="{'readonly': [('set_invoice_user_id', '=', False)]}"/>
|
||||||
<field name="date"/>
|
<field name="set_invoice_date" attrs="{'invisible': [('is_single_move', '=', True)]}"/>
|
||||||
|
<field name="invoice_date" attrs="{'readonly': [('set_invoice_date', '=', False)]}"/>
|
||||||
|
<field name="set_date" attrs="{'invisible': [('is_single_move', '=', True)]}"/>
|
||||||
|
<field name="date" attrs="{'readonly': [('set_date', '=', False)]}"/>
|
||||||
</group>
|
</group>
|
||||||
<group name="group_right"/>
|
<group name="group_right"/>
|
||||||
</group>
|
</group>
|
||||||
@@ -40,7 +44,6 @@
|
|||||||
<button name="%(action_view_account_invoice_change)d" string="Change"
|
<button name="%(action_view_account_invoice_change)d" string="Change"
|
||||||
type="action" class="btn-secondary"
|
type="action" class="btn-secondary"
|
||||||
attrs="{'invisible': ['|', ('state', 'in', ('draft', 'cancel')), ('type', 'not in', ('out_invoice', 'out_refund'))]}"
|
attrs="{'invisible': ['|', ('state', 'in', ('draft', 'cancel')), ('type', 'not in', ('out_invoice', 'out_refund'))]}"
|
||||||
context="{'default_move_id': id}"
|
|
||||||
groups="account.group_account_manager" />
|
groups="account.group_account_manager" />
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ class TestWizard(InvoiceChangeCommon):
|
|||||||
self.assertFalse(invoice_lines.analytic_account_id)
|
self.assertFalse(invoice_lines.analytic_account_id)
|
||||||
self.assertFalse(other_lines.analytic_account_id)
|
self.assertFalse(other_lines.analytic_account_id)
|
||||||
self.assertFalse(invoice_lines.analytic_line_ids)
|
self.assertFalse(invoice_lines.analytic_line_ids)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_invoice_change_analytic_tags(self):
|
def test_invoice_change_analytic_tags(self):
|
||||||
invoice_lines = self.invoice_basic.invoice_line_ids
|
invoice_lines = self.invoice_basic.invoice_line_ids
|
||||||
@@ -114,3 +112,23 @@ class TestWizard(InvoiceChangeCommon):
|
|||||||
self.assertEqual(invoice_lines.analytic_line_ids.mapped(lambda l: (l.account_id, l.amount)),
|
self.assertEqual(invoice_lines.analytic_line_ids.mapped(lambda l: (l.account_id, l.amount)),
|
||||||
[(self.analytic_account, 600.0),
|
[(self.analytic_account, 600.0),
|
||||||
(self.analytic_account3, 400.0)])
|
(self.analytic_account3, 400.0)])
|
||||||
|
|
||||||
|
def test_invoice_change_tags_multiple(self):
|
||||||
|
other_invoice = self.invoice_basic.copy()
|
||||||
|
self.invoice_basic.invoice_line_ids.analytic_account_id = self.analytic_account
|
||||||
|
self.invoice_basic.action_post()
|
||||||
|
other_invoice.invoice_line_ids.analytic_account_id = self.analytic_account2
|
||||||
|
other_invoice.action_post()
|
||||||
|
|
||||||
|
ctx = {'active_model': 'account.move', 'active_ids': [self.invoice_basic.id, other_invoice.id]}
|
||||||
|
change = Form(self.env['account.invoice.change'].with_context(ctx))
|
||||||
|
change.update_tags = 'set'
|
||||||
|
change.analytic_tag_ids.add(self.analytic_tag1)
|
||||||
|
change.save().affect_change()
|
||||||
|
|
||||||
|
# Unchanged unless user chooses to set the value
|
||||||
|
self.assertEqual(self.invoice_basic.invoice_line_ids.analytic_account_id, self.analytic_account)
|
||||||
|
self.assertEqual(other_invoice.invoice_line_ids.analytic_account_id, self.analytic_account2)
|
||||||
|
|
||||||
|
self.assertEqual(self.invoice_basic.invoice_line_ids.analytic_tag_ids, self.analytic_tag1)
|
||||||
|
self.assertEqual(other_invoice.invoice_line_ids.analytic_tag_ids, self.analytic_tag1)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
_inherit = 'account.invoice.change'
|
_inherit = 'account.invoice.change'
|
||||||
|
|
||||||
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
|
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
|
||||||
|
set_analytic_account_id = fields.Boolean()
|
||||||
update_tags = fields.Selection(selection=[
|
update_tags = fields.Selection(selection=[
|
||||||
('no', 'Do not update tags'),
|
('no', 'Do not update tags'),
|
||||||
('add', 'Add to tags'),
|
('add', 'Add to tags'),
|
||||||
@@ -21,11 +22,14 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
@api.model
|
@api.model
|
||||||
def default_get(self, fields):
|
def default_get(self, fields):
|
||||||
rec = super(InvoiceChangeWizard, self).default_get(fields)
|
rec = super(InvoiceChangeWizard, self).default_get(fields)
|
||||||
invoice = self.env['account.move'].browse(rec['move_id'])
|
context = dict(self._context or {})
|
||||||
rec.update({
|
invoices = self.env['account.move'].browse(context.get('active_ids'))
|
||||||
'analytic_account_id': self._analytic_account_id(invoice),
|
if len(invoices) == 1:
|
||||||
'analytic_tag_ids': [(6, 0, invoice.invoice_line_ids.analytic_tag_ids.ids)],
|
rec.update({
|
||||||
})
|
'set_analytic_account_id': True,
|
||||||
|
'analytic_account_id': self._analytic_account_id(invoices),
|
||||||
|
'analytic_tag_ids': [(6, 0, invoices.invoice_line_ids.analytic_tag_ids.ids)],
|
||||||
|
})
|
||||||
return rec
|
return rec
|
||||||
|
|
||||||
def affect_change(self):
|
def affect_change(self):
|
||||||
@@ -34,10 +38,9 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def _prepare_analytic_values(self):
|
def _prepare_analytic_values(self):
|
||||||
vals = {
|
vals = {}
|
||||||
'analytic_account_id': self.analytic_account_id.id,
|
if self.set_analytic_account_id:
|
||||||
'analytic_line_ids': [(5, 0, 0)],
|
vals['analytic_account_id'] = self.analytic_account_id.id
|
||||||
}
|
|
||||||
tag_commands = []
|
tag_commands = []
|
||||||
if self.update_tags == 'add':
|
if self.update_tags == 'add':
|
||||||
tag_commands = [(4, tag.id, 0) for tag in self.analytic_tag_ids]
|
tag_commands = [(4, tag.id, 0) for tag in self.analytic_tag_ids]
|
||||||
@@ -45,9 +48,13 @@ class InvoiceChangeWizard(models.TransientModel):
|
|||||||
tag_commands = [(6, 0, self.analytic_tag_ids.ids)]
|
tag_commands = [(6, 0, self.analytic_tag_ids.ids)]
|
||||||
if tag_commands:
|
if tag_commands:
|
||||||
vals['analytic_tag_ids'] = tag_commands
|
vals['analytic_tag_ids'] = tag_commands
|
||||||
|
if vals:
|
||||||
|
vals['analytic_line_ids'] = [(5, 0, 0)]
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
def _affect_analytic_change(self):
|
def _affect_analytic_change(self):
|
||||||
lines_to_affect = self.move_id.invoice_line_ids
|
lines_to_affect = self.move_ids.invoice_line_ids
|
||||||
lines_to_affect.write(self._prepare_analytic_values())
|
vals = self._prepare_analytic_values()
|
||||||
lines_to_affect.create_analytic_lines()
|
if vals:
|
||||||
|
lines_to_affect.write(vals)
|
||||||
|
lines_to_affect.create_analytic_lines()
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
<field name="inherit_id" ref="account_invoice_change.account_invoice_change_form"/>
|
<field name="inherit_id" ref="account_invoice_change.account_invoice_change_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//group[@name='group_right']" position="inside">
|
<xpath expr="//group[@name='group_right']" position="inside">
|
||||||
|
<field name="set_analytic_account_id" attr="('invisible': [('is_single_move', '=', True)]}" groups="analytic.group_analytic_accounting"/>
|
||||||
<field name="analytic_account_id"
|
<field name="analytic_account_id"
|
||||||
domain="['|', ('company_id', '=', False), ('company_id', '=', move_company_id)]"
|
domain="['|', ('company_id', '=', False), ('company_id', '=', move_company_id)]"
|
||||||
|
attrs="{'readonly': [('set_analytic_account_id', '=', False)]}"
|
||||||
groups="analytic.group_analytic_accounting"/>
|
groups="analytic.group_analytic_accounting"/>
|
||||||
<field name="update_tags" groups="analytic.group_analytic_tags"/>
|
<field name="update_tags" groups="analytic.group_analytic_tags"/>
|
||||||
<field name="analytic_tag_ids"
|
<field name="analytic_tag_ids"
|
||||||
|
|||||||
Reference in New Issue
Block a user