[FIX] account: Allow a Billing user to create an invoice/credit note
Purpose ======= When validation his first invoice/credit note, a billing user can choose which number will be the first on the invoice sequencing but it will raise a access right issue Specification ============= We want to allow a billing user to do it, but we can't give him the right to write on the ir_sequence. For that reason, we won't modify the ir.sequence field on the journal and skip this part. The field won't be displayed too on the form. Additional Point: ~~~~~~~~~~~~~~~~~ A cleaning of the code has been made to avoid raise conditions even when the first invoice has been created (2 users creating 2 invoices before having one validated).
This commit is contained in:
@@ -353,44 +353,57 @@ class AccountInvoice(models.Model):
|
||||
('number_uniq', 'unique(number, company_id, journal_id, type)', 'Invoice Number must be unique per Company!'),
|
||||
]
|
||||
|
||||
def _no_existing_validated_invoice(self):
|
||||
self.ensure_one()
|
||||
if self.journal_id.refund_sequence:
|
||||
domain = [('type', '=', self.type)]
|
||||
elif self.type in ['in_invoice', 'in_refund']:
|
||||
domain = [('type', 'in', ['in_invoice', 'in_refund'])]
|
||||
else:
|
||||
domain = [('type', 'in', ['out_invoice', 'out_refund'])]
|
||||
if self.id:
|
||||
domain += [('id', '<>', self.id)]
|
||||
domain += [('journal_id', '=', self.journal_id.id), ('state', 'not in', ['draft', 'cancel'])]
|
||||
return not self.search(domain, limit=1)
|
||||
|
||||
@api.depends('state', 'journal_id', 'date_invoice')
|
||||
def _get_sequence_prefix(self):
|
||||
""" computes the number that will be assigned to the first invoice/bill/refund of a journal, in order to
|
||||
let the user manually change it.
|
||||
"""
|
||||
if not self.env.user._is_admin():
|
||||
for invoice in self:
|
||||
invoice.sequence_number_next_prefix = False
|
||||
invoice.sequence_number_next = ''
|
||||
return
|
||||
for invoice in self:
|
||||
journal_sequence = invoice.journal_id.sequence_id
|
||||
if invoice.journal_id.refund_sequence:
|
||||
domain = [('type', '=', invoice.type)]
|
||||
journal_sequence = invoice.type in ['in_refund', 'out_refund'] and invoice.journal_id.refund_sequence_id or invoice.journal_id.sequence_id
|
||||
elif invoice.type in ['in_invoice', 'in_refund']:
|
||||
domain = [('type', 'in', ['in_invoice', 'in_refund'])]
|
||||
else:
|
||||
domain = [('type', 'in', ['out_invoice', 'out_refund'])]
|
||||
if invoice.id:
|
||||
domain += [('id', '<>', invoice.id)]
|
||||
domain += [('journal_id', '=', invoice.journal_id.id), ('state', 'not in', ['draft', 'cancel'])]
|
||||
journal_sequence = invoice.journal_id.sequence_id
|
||||
|
||||
if (invoice.state == 'draft') and not self.search(domain, limit=1):
|
||||
if (invoice.state == 'draft') and self._no_existing_validated_invoice():
|
||||
prefix, dummy = journal_sequence.with_context(ir_sequence_date=invoice.date_invoice)._get_prefix_suffix()
|
||||
invoice.sequence_number_next_prefix = prefix
|
||||
number_next = journal_sequence._get_current_sequence().number_next_actual
|
||||
invoice.sequence_number_next = '%%0%sd' % journal_sequence.padding % number_next
|
||||
else:
|
||||
invoice.sequence_number_next_prefix = False
|
||||
invoice.sequence_number_next = 'no'
|
||||
invoice.sequence_number_next = ''
|
||||
|
||||
@api.multi
|
||||
def _set_sequence_next(self):
|
||||
''' Set the number_next on the sequence related to the invoice/bill/refund'''
|
||||
for invoice in self:
|
||||
nxt = re.sub("[^0-9]", '', invoice.sequence_number_next or '1')
|
||||
result = re.match("(0*)([0-9]+)", nxt)
|
||||
journal_sequence = invoice.journal_id.refund_sequence and invoice.journal_id.refund_sequence_id or invoice.journal_id.sequence_id
|
||||
if result and journal_sequence:
|
||||
#use _get_current_sequence to manage the date range sequences
|
||||
sequence = journal_sequence._get_current_sequence()
|
||||
sequence.number_next = int(result.group(2))
|
||||
self.ensure_one()
|
||||
if not self.env.user._is_admin() or not self.sequence_number_next or not self._no_existing_validated_invoice():
|
||||
return
|
||||
nxt = re.sub("[^0-9]", '', self.sequence_number_next)
|
||||
result = re.match("(0*)([0-9]+)", nxt)
|
||||
journal_sequence = self.journal_id.refund_sequence and self.journal_id.refund_sequence_id or self.journal_id.sequence_id
|
||||
if result and journal_sequence:
|
||||
#use _get_current_sequence to manage the date range sequences
|
||||
sequence = journal_sequence._get_current_sequence()
|
||||
sequence.number_next = int(result.group(2))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
<field name="number" class="oe_inline" attrs="{'invisible': [('state', '=', 'draft')]}"/>
|
||||
<div attrs="{'invisible': [('sequence_number_next_prefix','=',False)]}">
|
||||
<field name="sequence_number_next_prefix" class="oe_inline"/>
|
||||
<field name="sequence_number_next" class="oe_inline" required="1" style="width: 80px !important;"/>
|
||||
<field name="sequence_number_next" class="oe_inline" style="width: 80px !important;"/>
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
@@ -378,7 +378,7 @@
|
||||
<div attrs="{'invisible': [('sequence_number_next_prefix','=',False)]}">
|
||||
<label string="Invoice Number:"/><br/>
|
||||
<field name="sequence_number_next_prefix" class="oe_inline"/>
|
||||
<field name="sequence_number_next" class="oe_inline" required="1" style="width: 80px !important;"/>
|
||||
<field name="sequence_number_next" class="oe_inline" style="width: 80px !important;"/>
|
||||
</div>
|
||||
</h1>
|
||||
<field name="type" invisible="1"/>
|
||||
|
||||
Reference in New Issue
Block a user