[IMP] account: dedicated payments sequence
Add setting on bank/cash journals to have dedicated payments sequences Enabled by default closes odoo/odoo#99058 See: odoo/enterprise#31059 Task: 2894299 Signed-off-by: Laurent Smet <las@odoo.com>
This commit is contained in:
@@ -108,6 +108,7 @@ class AccountJournal(models.Model):
|
||||
country_code = fields.Char(related='company_id.account_fiscal_country_id.code', readonly=True)
|
||||
|
||||
refund_sequence = fields.Boolean(string='Dedicated Credit Note Sequence', help="Check this box if you don't want to share the same sequence for invoices and credit notes made from this journal", default=False)
|
||||
payment_sequence = fields.Boolean(string='Dedicated Payment Sequence', help="Check this box if you don't want to share the same sequence on payments and bank transactions posted on this journal", default='_compute_payment_sequence')
|
||||
sequence_override_regex = fields.Text(help="Technical field used to enforce complex sequence composition that the system would normally misunderstand.\n"\
|
||||
"This is a regex that can include all the following capture groups: prefix1, year, prefix2, month, prefix3, seq, suffix.\n"\
|
||||
"The prefix* groups are the separators between the year, month and the actual increasing sequence number (seq).\n"\
|
||||
@@ -483,6 +484,11 @@ class AccountJournal(models.Model):
|
||||
def _onchange_type(self):
|
||||
self.refund_sequence = self.type in ('sale', 'purchase')
|
||||
|
||||
@api.depends('type')
|
||||
def _compute_payment_sequence(self):
|
||||
for journal in self:
|
||||
journal.payment_sequence = journal.type in ('bank', 'cash')
|
||||
|
||||
def unlink(self):
|
||||
bank_accounts = self.env['res.partner.bank'].browse()
|
||||
for bank_account in self.mapped('bank_account_id'):
|
||||
|
||||
@@ -2248,12 +2248,15 @@ class AccountMove(models.Model):
|
||||
return "WHERE FALSE", {}
|
||||
where_string = "WHERE journal_id = %(journal_id)s AND name != '/'"
|
||||
param = {'journal_id': self.journal_id.id}
|
||||
is_payment = self.payment_id or self._context.get('is_payment')
|
||||
|
||||
if not relaxed:
|
||||
domain = [('journal_id', '=', self.journal_id.id), ('id', '!=', self.id or self._origin.id), ('name', 'not in', ('/', '', False))]
|
||||
if self.journal_id.refund_sequence:
|
||||
refund_types = ('out_refund', 'in_refund')
|
||||
domain += [('move_type', 'in' if self.move_type in refund_types else 'not in', refund_types)]
|
||||
if self.journal_id.payment_sequence:
|
||||
domain += [('payment_id', '!=' if is_payment else '=', False)]
|
||||
reference_move_name = self.search(domain + [('date', '<=', self.date)], order='date desc', limit=1).name
|
||||
if not reference_move_name:
|
||||
reference_move_name = self.search(domain, order='date asc', limit=1).name
|
||||
@@ -2276,18 +2279,26 @@ class AccountMove(models.Model):
|
||||
where_string += " AND move_type IN ('out_refund', 'in_refund') "
|
||||
else:
|
||||
where_string += " AND move_type NOT IN ('out_refund', 'in_refund') "
|
||||
elif self.journal_id.payment_sequence:
|
||||
if is_payment:
|
||||
where_string += " AND payment_id IS NOT NULL "
|
||||
else:
|
||||
where_string += " AND payment_id IS NULL "
|
||||
|
||||
return where_string, param
|
||||
|
||||
def _get_starting_sequence(self):
|
||||
# EXTENDS account sequence.mixin
|
||||
self.ensure_one()
|
||||
is_payment = self.payment_id or self._context.get('is_payment')
|
||||
if self.journal_id.type == 'sale':
|
||||
starting_sequence = "%s/%04d/00000" % (self.journal_id.code, self.date.year)
|
||||
else:
|
||||
starting_sequence = "%s/%04d/%02d/0000" % (self.journal_id.code, self.date.year, self.date.month)
|
||||
if self.journal_id.refund_sequence and self.move_type in ('out_refund', 'in_refund'):
|
||||
starting_sequence = "R" + starting_sequence
|
||||
if self.journal_id.payment_sequence and is_payment:
|
||||
starting_sequence = "P" + starting_sequence
|
||||
return starting_sequence
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@@ -692,8 +692,7 @@ class AccountPayment(models.Model):
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def new(self, values=None, origin=None, ref=None):
|
||||
self = self.with_context(is_payment=True)
|
||||
payment = super().new(values, origin, ref)
|
||||
payment = super(AccountPayment, self.with_context(is_payment=True)).new(values, origin, ref)
|
||||
if not payment.journal_id: # might not be computed because declared by inheritance
|
||||
payment.move_id._compute_journal_id()
|
||||
return payment
|
||||
@@ -701,7 +700,6 @@ class AccountPayment(models.Model):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# OVERRIDE
|
||||
self = self.with_context(is_payment=True)
|
||||
write_off_line_vals_list = []
|
||||
|
||||
for vals in vals_list:
|
||||
@@ -712,7 +710,9 @@ class AccountPayment(models.Model):
|
||||
# Force the move_type to avoid inconsistency with residual 'default_move_type' inside the context.
|
||||
vals['move_type'] = 'entry'
|
||||
|
||||
payments = super().create(vals_list)
|
||||
payments = super(AccountPayment, self.with_context(is_payment=True))\
|
||||
.create(vals_list)\
|
||||
.with_context(is_payment=False)
|
||||
|
||||
for i, pay in enumerate(payments):
|
||||
write_off_line_vals = write_off_line_vals_list[i]
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
options="{'no_quick_create': True}"
|
||||
groups="account.group_account_readonly"/>
|
||||
<field name="refund_sequence" attrs="{'invisible': [('type', 'not in', ['sale', 'purchase'])]}"/>
|
||||
<field name="payment_sequence" attrs="{'invisible': [('type', 'not in', ('bank', 'cash'))]}"/>
|
||||
<field name="code" placeholder="e.g. INV"/>
|
||||
<field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/>
|
||||
</group>
|
||||
|
||||
@@ -39,6 +39,9 @@ class ReSequenceWizard(models.TransientModel):
|
||||
and len(move_types) > 1
|
||||
):
|
||||
raise UserError(_('The sequences of this journal are different for Invoices and Refunds but you selected some of both types.'))
|
||||
is_payment = set(active_move_ids.mapped(lambda x: bool(x.payment_id)))
|
||||
if len(is_payment) > 1:
|
||||
raise UserError(_('The sequences of this journal are different for Payments and non-Payments but you selected some of both types.'))
|
||||
values['move_ids'] = [(6, 0, active_move_ids.ids)]
|
||||
return values
|
||||
|
||||
|
||||
Reference in New Issue
Block a user