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',
|
||||
],
|
||||
'data': [
|
||||
'data/server_actions.xml',
|
||||
'wizard/invoice_change_views.xml',
|
||||
],
|
||||
'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.tests import tagged
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged, Form
|
||||
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(self.invoice_basic.invoice_user_id, change_user)
|
||||
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'
|
||||
_description = 'Invoice Change'
|
||||
|
||||
move_id = fields.Many2one('account.move', string='Invoice', readonly=True, required=True)
|
||||
move_company_id = fields.Many2one('res.company', readonly=True, related='move_id.company_id')
|
||||
move_ids = fields.Many2many('account.move', string='Invoice', readonly=True, required=True)
|
||||
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')
|
||||
set_invoice_user_id = fields.Boolean()
|
||||
date = fields.Date(string='Accounting Date')
|
||||
set_date = fields.Boolean()
|
||||
invoice_date = fields.Date(string='Invoice Date')
|
||||
set_invoice_date = fields.Boolean()
|
||||
|
||||
@api.model
|
||||
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)
|
||||
|
||||
# Checks on received invoice records
|
||||
invoice = self.env[active_model].browse(active_ids)
|
||||
if len(invoice) != 1:
|
||||
raise UserError(_("Invoice Change expects only one invoice."))
|
||||
rec.update({
|
||||
'move_id': invoice.id,
|
||||
'invoice_user_id': invoice.invoice_user_id.id,
|
||||
'date': invoice.date,
|
||||
'invoice_date': invoice.invoice_date,
|
||||
})
|
||||
invoices = self.env[active_model].browse(active_ids)
|
||||
if invoices.filtered(lambda i: not i.is_invoice()):
|
||||
raise UserError(_('Only invoices can be updated.'))
|
||||
if invoices.filtered(lambda i: i.state in ('draft', 'cancel')):
|
||||
raise UserError(_('Only posted invoices can be updated.'))
|
||||
if len(invoices.company_id) > 1:
|
||||
raise UserError(_('Selected invoices must be in the same company.'))
|
||||
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
|
||||
|
||||
@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):
|
||||
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
|
||||
if self.move_id.date != self.date:
|
||||
if self.set_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
|
||||
return vals
|
||||
|
||||
@@ -53,5 +73,5 @@ class InvoiceChangeWizard(models.TransientModel):
|
||||
self.ensure_one()
|
||||
vals = self._new_move_vals()
|
||||
if vals:
|
||||
self.move_id.write(vals)
|
||||
self.move_ids.write(vals)
|
||||
return True
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
<form string="Invoice Change">
|
||||
<group>
|
||||
<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="invoice_user_id"/>
|
||||
<field name="invoice_date"/>
|
||||
<field name="date"/>
|
||||
<field name="set_invoice_user_id" attrs="{'invisible': [('is_single_move', '=', True)]}"/>
|
||||
<field name="invoice_user_id" attrs="{'readonly': [('set_invoice_user_id', '=', False)]}"/>
|
||||
<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 name="group_right"/>
|
||||
</group>
|
||||
@@ -40,7 +44,6 @@
|
||||
<button name="%(action_view_account_invoice_change)d" string="Change"
|
||||
type="action" class="btn-secondary"
|
||||
attrs="{'invisible': ['|', ('state', 'in', ('draft', 'cancel')), ('type', 'not in', ('out_invoice', 'out_refund'))]}"
|
||||
context="{'default_move_id': id}"
|
||||
groups="account.group_account_manager" />
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -68,8 +68,6 @@ class TestWizard(InvoiceChangeCommon):
|
||||
self.assertFalse(other_lines.analytic_account_id)
|
||||
self.assertFalse(invoice_lines.analytic_line_ids)
|
||||
|
||||
|
||||
|
||||
def test_invoice_change_analytic_tags(self):
|
||||
invoice_lines = self.invoice_basic.invoice_line_ids
|
||||
other_lines = self.invoice_basic.line_ids - invoice_lines
|
||||
@@ -114,3 +112,23 @@ class TestWizard(InvoiceChangeCommon):
|
||||
self.assertEqual(invoice_lines.analytic_line_ids.mapped(lambda l: (l.account_id, l.amount)),
|
||||
[(self.analytic_account, 600.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'
|
||||
|
||||
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
|
||||
set_analytic_account_id = fields.Boolean()
|
||||
update_tags = fields.Selection(selection=[
|
||||
('no', 'Do not update tags'),
|
||||
('add', 'Add to tags'),
|
||||
@@ -21,11 +22,14 @@ class InvoiceChangeWizard(models.TransientModel):
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
rec = super(InvoiceChangeWizard, self).default_get(fields)
|
||||
invoice = self.env['account.move'].browse(rec['move_id'])
|
||||
rec.update({
|
||||
'analytic_account_id': self._analytic_account_id(invoice),
|
||||
'analytic_tag_ids': [(6, 0, invoice.invoice_line_ids.analytic_tag_ids.ids)],
|
||||
})
|
||||
context = dict(self._context or {})
|
||||
invoices = self.env['account.move'].browse(context.get('active_ids'))
|
||||
if len(invoices) == 1:
|
||||
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
|
||||
|
||||
def affect_change(self):
|
||||
@@ -34,10 +38,9 @@ class InvoiceChangeWizard(models.TransientModel):
|
||||
return res
|
||||
|
||||
def _prepare_analytic_values(self):
|
||||
vals = {
|
||||
'analytic_account_id': self.analytic_account_id.id,
|
||||
'analytic_line_ids': [(5, 0, 0)],
|
||||
}
|
||||
vals = {}
|
||||
if self.set_analytic_account_id:
|
||||
vals['analytic_account_id'] = self.analytic_account_id.id
|
||||
tag_commands = []
|
||||
if self.update_tags == 'add':
|
||||
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)]
|
||||
if tag_commands:
|
||||
vals['analytic_tag_ids'] = tag_commands
|
||||
if vals:
|
||||
vals['analytic_line_ids'] = [(5, 0, 0)]
|
||||
return vals
|
||||
|
||||
def _affect_analytic_change(self):
|
||||
lines_to_affect = self.move_id.invoice_line_ids
|
||||
lines_to_affect.write(self._prepare_analytic_values())
|
||||
lines_to_affect.create_analytic_lines()
|
||||
lines_to_affect = self.move_ids.invoice_line_ids
|
||||
vals = self._prepare_analytic_values()
|
||||
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="arch" type="xml">
|
||||
<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"
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', move_company_id)]"
|
||||
attrs="{'readonly': [('set_analytic_account_id', '=', False)]}"
|
||||
groups="analytic.group_analytic_accounting"/>
|
||||
<field name="update_tags" groups="analytic.group_analytic_tags"/>
|
||||
<field name="analytic_tag_ids"
|
||||
|
||||
Reference in New Issue
Block a user