[IMP] account: Reversal on same journal type as original AccountMove
For data quality purposes and bug prevention, when I reverse an entry, the reversal should always be postable on a journal having the same type as the initial Journal Entry's journal. closes odoo/odoo#72431 Task: 2497529 Related: odoo/enterprise#19543 Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
This commit is contained in:
@@ -1141,6 +1141,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2019-02-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'refund',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1192,6 +1193,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2019-02-01'),
|
||||
'reason': 'no reason again',
|
||||
'refund_method': 'cancel',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1255,6 +1257,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2017-01-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'refund',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1312,6 +1315,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2017-01-01'),
|
||||
'reason': 'no reason again',
|
||||
'refund_method': 'cancel',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
|
||||
@@ -1746,6 +1746,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2019-02-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'refund',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1798,6 +1799,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2019-02-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'cancel',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1861,6 +1863,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2017-01-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'refund',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1918,6 +1921,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.from_string('2017-01-01'),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'cancel',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reverse_move = self.env['account.move'].browse(reversal['res_id'])
|
||||
@@ -1978,6 +1982,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
'date': fields.Date.today() + timedelta(days=7),
|
||||
'reason': 'no reason',
|
||||
'refund_method': 'modify',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
move_reversal.reverse_moves()
|
||||
refund = self.env['account.move'].search([('move_type', '=', 'out_refund'), ('company_id', '=', self.invoice.company_id.id)])
|
||||
|
||||
@@ -26,14 +26,50 @@ class AccountMoveReversal(models.TransientModel):
|
||||
('modify', 'Full refund and new draft invoice')
|
||||
], string='Credit Method', required=True,
|
||||
help='Choose how you want to credit this invoice. You cannot "modify" nor "cancel" if the invoice is already reconciled.')
|
||||
journal_id = fields.Many2one('account.journal', string='Use Specific Journal', help='If empty, uses the journal of the journal entry to be reversed.', check_company=True)
|
||||
journal_id = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
string='Use Specific Journal',
|
||||
required=True,
|
||||
compute='_compute_journal_id',
|
||||
readonly=False,
|
||||
store=True,
|
||||
check_company=True,
|
||||
help='If empty, uses the journal of the journal entry to be reversed.',
|
||||
)
|
||||
company_id = fields.Many2one('res.company', required=True, readonly=True)
|
||||
available_journal_ids = fields.Many2many('account.journal', compute='_compute_available_journal_ids')
|
||||
|
||||
# computed fields
|
||||
residual = fields.Monetary(compute="_compute_from_moves")
|
||||
currency_id = fields.Many2one('res.currency', compute="_compute_from_moves")
|
||||
move_type = fields.Char(compute="_compute_from_moves")
|
||||
|
||||
@api.depends('move_ids')
|
||||
def _compute_journal_id(self):
|
||||
for record in self:
|
||||
if record.journal_id:
|
||||
record.journal_id = record.journal_id
|
||||
else:
|
||||
journals = record.move_ids.journal_id.filtered(lambda x: x.active)
|
||||
record.journal_id = journals[0] if journals else None
|
||||
|
||||
@api.depends('move_ids')
|
||||
def _compute_available_journal_ids(self):
|
||||
for record in self:
|
||||
if record.move_ids:
|
||||
record.available_journal_ids = self.env['account.journal'].search([
|
||||
('company_id', '=', record.company_id.id),
|
||||
('type', 'in', record.move_ids.journal_id.mapped('type')),
|
||||
])
|
||||
else:
|
||||
record.available_journal_ids = self.env['account.journal'].search([('company_id', '=', record.company_id.id)])
|
||||
|
||||
@api.constrains('journal_id', 'move_ids')
|
||||
def _check_journal_type(self):
|
||||
for record in self:
|
||||
if record.journal_id.type not in record.move_ids.journal_id.mapped('type'):
|
||||
raise UserError(_('Journal should be of type of reversed entry.'))
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(AccountMoveReversal, self).default_get(fields)
|
||||
@@ -65,7 +101,7 @@ class AccountMoveReversal(models.TransientModel):
|
||||
else _('Reversal of: %s', move.name),
|
||||
'date': reverse_date,
|
||||
'invoice_date': move.is_invoice(include_receipts=True) and (self.date or move.date) or False,
|
||||
'journal_id': self.journal_id and self.journal_id.id or move.journal_id.id,
|
||||
'journal_id': self.journal_id.id,
|
||||
'invoice_payment_term_id': None,
|
||||
'invoice_user_id': move.invoice_user_id.id,
|
||||
'auto_post': True if reverse_date > fields.Date.context_today(self) else False,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="move_ids" invisible="1"/>
|
||||
<field name="move_type" invisible="1"/>
|
||||
<field name="available_journal_ids" invisible="1"/>
|
||||
<group>
|
||||
<group attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'in_invoice'))]}">
|
||||
<field name="refund_method" widget="radio" attrs="{'readonly': [('residual', '=', 0)]}"/>
|
||||
@@ -28,15 +29,15 @@
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<group>
|
||||
<field name="reason" attrs="{'invisible': [('move_type', '=', 'entry')]}"/>
|
||||
<field name="date_mode" string="Reversal Date" widget="radio"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="journal_id"/>
|
||||
<field name="date" string="Refund Date" attrs="{'invisible': ['|', ('move_type', 'not in', ('out_invoice', 'in_invoice')), ('date_mode', '!=', 'custom')], 'required':[('date_mode', '=', 'custom')]}"/>
|
||||
<field name="date" attrs="{'invisible': ['|', ('move_type', 'in', ('out_invoice', 'in_invoice')), ('date_mode', '!=', 'custom')], 'required':[('date_mode', '=', 'custom')]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="reason" attrs="{'invisible': [('move_type', '=', 'entry')]}"/>
|
||||
<field name="date_mode" string="Reversal Date" widget="radio"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="journal_id" domain="[('id', 'in', available_journal_ids)]"/>
|
||||
<field name="date" string="Refund Date" attrs="{'invisible': ['|', ('move_type', 'not in', ('out_invoice', 'in_invoice')), ('date_mode', '!=', 'custom')], 'required':[('date_mode', '=', 'custom')]}"/>
|
||||
<field name="date" attrs="{'invisible': ['|', ('move_type', 'in', ('out_invoice', 'in_invoice')), ('date_mode', '!=', 'custom')], 'required':[('date_mode', '=', 'custom')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button string='Reverse' name="reverse_moves" type="object" class="btn-primary"/>
|
||||
|
||||
@@ -109,6 +109,7 @@ class TestValuationReconciliation(ValuationReconciliationTestCommon):
|
||||
'reason': 'test_invoice_shipment_refund',
|
||||
'refund_method': 'cancel',
|
||||
'date': '2018-03-15',
|
||||
'journal_id': invoice.journal_id.id,
|
||||
})
|
||||
refund_invoice = self.env['account.move'].browse(refund_invoice_wiz.reverse_moves()['res_id'])
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ class TestSaleToInvoice(TestSaleCommon):
|
||||
credit_note_wizard = self.env['account.move.reversal'].with_context({'active_ids': [self.invoice.id], 'active_id': self.invoice.id, 'active_model': 'account.move'}).create({
|
||||
'refund_method': 'refund', # this is the only mode for which the SO line is linked to the refund (https://github.com/odoo/odoo/commit/e680f29560ac20133c7af0c6364c6ef494662eac)
|
||||
'reason': 'reason test create',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
credit_note_wizard.reverse_moves()
|
||||
invoice_refund = self.sale_order.invoice_ids.sorted(key=lambda inv: inv.id, reverse=False)[-1] # the first invoice, its refund, and the new invoice
|
||||
@@ -191,6 +192,7 @@ class TestSaleToInvoice(TestSaleCommon):
|
||||
credit_note_wizard = self.env['account.move.reversal'].with_context({'active_ids': self.invoice.ids, 'active_id': self.invoice.id, 'active_model': 'account.move'}).create({
|
||||
'refund_method': 'cancel',
|
||||
'reason': 'reason test cancel',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
invoice_refund = self.env['account.move'].browse(credit_note_wizard.reverse_moves()['res_id'])
|
||||
|
||||
@@ -253,6 +255,7 @@ class TestSaleToInvoice(TestSaleCommon):
|
||||
credit_note_wizard = self.env['account.move.reversal'].with_context({'active_ids': [self.invoice.id], 'active_id': self.invoice.id, 'active_model': 'account.move'}).create({
|
||||
'refund_method': 'modify', # this is the only mode for which the SO line is linked to the refund (https://github.com/odoo/odoo/commit/e680f29560ac20133c7af0c6364c6ef494662eac)
|
||||
'reason': 'reason test modify',
|
||||
'journal_id': self.invoice.journal_id.id,
|
||||
})
|
||||
invoice_refund = self.env['account.move'].browse(credit_note_wizard.reverse_moves()['res_id'])
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ class TestValuationReconciliation(ValuationReconciliationTestCommon):
|
||||
refund_invoice_wiz = self.env['account.move.reversal'].with_context(active_model='account.move', active_ids=[invoice.id]).create({
|
||||
'reason': 'test_invoice_shipment_refund',
|
||||
'refund_method': 'cancel',
|
||||
'journal_id': invoice.journal_id.id,
|
||||
})
|
||||
refund_invoice = self.env['account.move'].browse(refund_invoice_wiz.reverse_moves()['res_id'])
|
||||
self.assertEqual(invoice.payment_state, 'reversed', "Invoice should be in 'reversed' state.")
|
||||
|
||||
Reference in New Issue
Block a user