diff options
| author | wan <wan@odoo.com> | 2019-11-27 15:57:42 +0000 |
|---|---|---|
| committer | wan <wan@odoo.com> | 2020-02-05 13:59:43 +0000 |
| commit | dfd01b8c5c7e1177f37bf199790a0732a61eed78 (patch) | |
| tree | 6ebb7f50ba554fb4138954c958f799836aae91a7 /addons/l10n_latam_invoice_document | |
| parent | a6d7c7b04a48669037e6568849a26571602386f6 (diff) | |
[IMP] account: rework name sequences
Task 2146469
Rework the name computation:
* It doesn't use ir.sequence anymore
* It is an editable computed field
* Add a renaming tool
This allows the user to tweak the sequences more easily than having to
get through the ir.sequence settings.
The sequence depends on a parameter of the journal: continuous, montly
and yearly restart of the sequence. Everytime a new period is started,
try to make a pattern form another period.
The incrementing is done by taking the previous name, ordered
lexicographically, splitting it by taking the digits at the end, adding
1 and re contstruct with the prefix.
** This means there could be cases where the prefix has a big importance
on the next number. For instance, if you have
INVOICE/2019/0001
INVOICE/2019/0002
and then rename the last one to INV/2019/0002, don't expect the next
number to be INV/2019/0003. It will be INVOICE/2019/0002 (again) because
the highest number was INVOICE/2019/0001.
You will then end up with
INVOICE/2019/0001
INV/2019/0002
INVOICE/2019/0002
closes odoo/odoo#41485
Related: odoo/enterprise#7189
Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
Diffstat (limited to 'addons/l10n_latam_invoice_document')
5 files changed, 51 insertions, 119 deletions
diff --git a/addons/l10n_latam_invoice_document/models/account_move.py b/addons/l10n_latam_invoice_document/models/account_move.py index fb6d8b0541b..52b8f960a74 100644 --- a/addons/l10n_latam_invoice_document/models/account_move.py +++ b/addons/l10n_latam_invoice_document/models/account_move.py @@ -3,6 +3,7 @@ from odoo import models, fields, api, _ from odoo.exceptions import UserError, ValidationError from functools import partial +import re from odoo.tools.misc import formatLang @@ -16,48 +17,27 @@ class AccountMove(models.Model): l10n_latam_document_type_id = fields.Many2one( 'l10n_latam.document.type', string='Document Type', copy=False, readonly=False, auto_join=True, index=True, states={'posted': [('readonly', True)]}, compute='_compute_l10n_latam_document_type', store=True) - l10n_latam_sequence_id = fields.Many2one('ir.sequence', compute='_compute_l10n_latam_sequence') - l10n_latam_document_number = fields.Char( - compute='_compute_l10n_latam_document_number', inverse='_inverse_l10n_latam_document_number', - string='Document Number', readonly=True, states={'draft': [('readonly', False)]}) l10n_latam_use_documents = fields.Boolean(related='journal_id.l10n_latam_use_documents') l10n_latam_country_code = fields.Char( related='company_id.country_id.code', help='Technical field used to hide/show fields regarding the localization') - def _get_sequence_prefix(self): - """ If we use documents we update sequences only from journal """ - return super(AccountMove, self.filtered(lambda x: not x.l10n_latam_use_documents))._get_sequence_prefix() - - @api.depends('name') - def _compute_l10n_latam_document_number(self): - recs_with_name = self.filtered(lambda x: x.name != '/') - for rec in recs_with_name: - name = rec.name - doc_code_prefix = rec.l10n_latam_document_type_id.doc_code_prefix - if doc_code_prefix and name: - name = name.split(" ", 1)[-1] - rec.l10n_latam_document_number = name - remaining = self - recs_with_name - remaining.l10n_latam_document_number = False - - @api.onchange('l10n_latam_document_type_id', 'l10n_latam_document_number') - def _inverse_l10n_latam_document_number(self): - for rec in self.filtered('l10n_latam_document_type_id'): - if not rec.l10n_latam_document_number: - rec.name = '/' - else: - l10n_latam_document_number = rec.l10n_latam_document_type_id._format_document_number(rec.l10n_latam_document_number) - if rec.l10n_latam_document_number != l10n_latam_document_number: - rec.l10n_latam_document_number = l10n_latam_document_number - rec.name = "%s %s" % (rec.l10n_latam_document_type_id.doc_code_prefix, l10n_latam_document_number) - - @api.depends('l10n_latam_document_type_id', 'journal_id') - def _compute_l10n_latam_sequence(self): - recs_with_journal_id = self.filtered('journal_id') - for rec in recs_with_journal_id: - rec.l10n_latam_sequence_id = rec._get_document_type_sequence() - remaining = self - recs_with_journal_id - remaining.l10n_latam_sequence_id = False + @api.model + def _deduce_sequence_number_reset(self, name): + if self.l10n_latam_use_documents: + return 'never' + return super(AccountMove, self)._deduce_sequence_number_reset(name) + + def _get_last_sequence_domain(self, relaxed=False): + where_string, param = super(AccountMove, self)._get_last_sequence_domain(relaxed) + if self.l10n_latam_use_documents: + where_string += " AND l10n_latam_document_type_id = %(l10n_latam_document_type_id)s " + param['l10n_latam_document_type_id'] = self.l10n_latam_document_type_id.id or 0 + return where_string, param + + def _get_starting_sequence(self): + if self.l10n_latam_use_documents: + return "%s 0001-00000000" % (self.l10n_latam_document_type_id.doc_code_prefix) + return super(AccountMove, self)._get_starting_sequence() def _compute_l10n_latam_amount_and_taxes(self): recs_invoice = self.filtered(lambda x: x.is_invoice()) @@ -82,20 +62,10 @@ class AccountMove(models.Model): remaining.l10n_latam_amount_untaxed = False remaining.l10n_latam_tax_ids = [(5, 0)] - def _compute_invoice_sequence_number_next(self): - """ If journal use documents disable the next number header""" - with_latam_document_number = self.filtered('l10n_latam_use_documents') - with_latam_document_number.invoice_sequence_number_next_prefix = False - with_latam_document_number.invoice_sequence_number_next = False - return super(AccountMove, self - with_latam_document_number)._compute_invoice_sequence_number_next() - def post(self): for rec in self.filtered(lambda x: x.l10n_latam_use_documents and (not x.name or x.name == '/')): - if not rec.l10n_latam_sequence_id: - raise UserError(_('No sequence or document number linked to invoice id %s') % rec.id) if rec.type in ('in_receipt', 'out_receipt'): raise UserError(_('We do not accept the usage of document types on receipts yet. ')) - rec.l10n_latam_document_number = rec.l10n_latam_sequence_id.next_by_id() return super().post() @api.constrains('name', 'journal_id', 'state') @@ -122,10 +92,10 @@ class AccountMove(models.Model): raise ValidationError(_( 'The journal require a document type but not document type has been selected on invoices %s.' % ( without_doc_type.ids))) - without_number = validated_invoices.filtered( - lambda x: not x.l10n_latam_document_number and not x.l10n_latam_sequence_id) + valid = re.compile(r'[A-Z\-]+\s*\d{1,5}\-\d{1,8}') + without_number = validated_invoices.filtered(lambda x: not valid.match(x.name)) if without_number: - raise ValidationError(_('Please set the document number on the following invoices %s.' % ( + raise ValidationError(_('The document number on the following invoices is not correct %s.' % ( without_number.ids))) @api.constrains('type', 'l10n_latam_document_type_id') @@ -193,24 +163,20 @@ class AccountMove(models.Model): ) for group, amounts in res] super(AccountMove, self - move_with_doc_type)._compute_invoice_taxes_by_group() - def _get_document_type_sequence(self): - """ Method to be inherited by different localizations. """ - self.ensure_one() - return self.env['ir.sequence'] - @api.constrains('name', 'partner_id', 'company_id') def _check_unique_vendor_number(self): """ The constraint _check_unique_sequence_number is valid for customer bills but not valid for us on vendor bills because the uniqueness must be per partner and also because we want to validate on entry creation and not on entry validation """ - for rec in self.filtered(lambda x: x.is_purchase_document() and x.l10n_latam_use_documents and x.l10n_latam_document_number): + for rec in self.filtered(lambda x: x.is_purchase_document() and x.l10n_latam_use_documents): domain = [ ('type', '=', rec.type), - # by validating name we validate l10n_latam_document_number and l10n_latam_document_type_id + # by validating name we validate l10n_latam_document_type_id ('name', '=', rec.name), ('company_id', '=', rec.company_id.id), ('id', '!=', rec.id), - ('commercial_partner_id', '=', rec.commercial_partner_id.id) + ('commercial_partner_id', '=', rec.commercial_partner_id.id), + ('posted_before', '=', True), ] if rec.search(domain): raise ValidationError(_('Vendor bill number must be unique per vendor and company.')) diff --git a/addons/l10n_latam_invoice_document/views/account_move_view.xml b/addons/l10n_latam_invoice_document/views/account_move_view.xml index a8df0d65233..32dd56279da 100644 --- a/addons/l10n_latam_invoice_document/views/account_move_view.xml +++ b/addons/l10n_latam_invoice_document/views/account_move_view.xml @@ -38,15 +38,12 @@ <field name="l10n_latam_available_document_type_ids" invisible="1"/> <field name="l10n_latam_use_documents" invisible="1"/> <field name="l10n_latam_country_code" invisible="1"/> - <field name="l10n_latam_sequence_id" invisible="1"/> </form> <field name="journal_id" position="after"> <field name="l10n_latam_document_type_id" attrs="{'invisible': [('l10n_latam_use_documents', '=', False)], 'required': [('l10n_latam_use_documents', '=', True)], 'readonly': [('state', '!=', 'draft')]}" domain="[('id', 'in', l10n_latam_available_document_type_ids)]" options="{'no_open': True, 'no_create': True}"/> - <field name="l10n_latam_document_number" - attrs="{'invisible': ['|', ('l10n_latam_sequence_id', '!=', False), ('l10n_latam_use_documents', '=', False)], 'required': [('l10n_latam_sequence_id', '=', False), ('l10n_latam_use_documents', '=', True)], 'readonly': [('state', '!=', 'draft')]}"/> </field> </field> </record> diff --git a/addons/l10n_latam_invoice_document/views/report_invoice.xml b/addons/l10n_latam_invoice_document/views/report_invoice.xml index fc2784bb033..f1a775f8888 100644 --- a/addons/l10n_latam_invoice_document/views/report_invoice.xml +++ b/addons/l10n_latam_invoice_document/views/report_invoice.xml @@ -13,7 +13,6 @@ <xpath expr="//h2" position="after"> <h2 t-if="o.l10n_latam_document_type_id.report_name"> <span t-field="o.l10n_latam_document_type_id.report_name"/> - <span t-field="o.l10n_latam_document_number"/> </h2> </xpath> diff --git a/addons/l10n_latam_invoice_document/wizards/account_move_reversal.py b/addons/l10n_latam_invoice_document/wizards/account_move_reversal.py index de81b3c6ba7..0169859a098 100644 --- a/addons/l10n_latam_invoice_document/wizards/account_move_reversal.py +++ b/addons/l10n_latam_invoice_document/wizards/account_move_reversal.py @@ -5,27 +5,11 @@ from odoo.exceptions import UserError class AccountMoveReversal(models.TransientModel): - _inherit = "account.move.reversal" - l10n_latam_use_documents = fields.Boolean(readonly=True) - l10n_latam_document_type_id = fields.Many2one('l10n_latam.document.type', 'Document Type', ondelete='cascade', domain="[('id', 'in', l10n_latam_available_document_type_ids)]") - l10n_latam_available_document_type_ids = fields.Many2many('l10n_latam.document.type', store=False) - l10n_latam_sequence_id = fields.Many2one('ir.sequence', compute='_compute_l10n_latam_sequence') - l10n_latam_document_number = fields.Char(string='Document Number') - - @api.model - def default_get(self, fields): - res = super(AccountMoveReversal, self).default_get(fields) - move_ids = self.env['account.move'].browse(self.env.context['active_ids']) if self.env.context.get('active_model') == 'account.move' else self.env['account.move'] - if len(move_ids) > 1: - move_ids_use_document = move_ids.filtered(lambda move: move.l10n_latam_use_documents) - if move_ids_use_document: - raise UserError(_('You can only reverse documents with legal invoicing documents from Latin America one at a time.\nProblematic documents: %s') % ", ".join(move_ids_use_document.mapped('name'))) - else: - res['l10n_latam_use_documents'] = move_ids.journal_id.l10n_latam_use_documents - - return res + l10n_latam_use_documents = fields.Boolean(compute='_compute_document_type') + l10n_latam_document_type_id = fields.Many2one('l10n_latam.document.type', 'Document Type', ondelete='cascade', domain="[('id', 'in', l10n_latam_available_document_type_ids)]", compute='_compute_document_type', readonly=False) + l10n_latam_available_document_type_ids = fields.Many2many('l10n_latam.document.type', compute='_compute_document_type') @api.model def _reverse_type_map(self, move_type): @@ -38,41 +22,29 @@ class AccountMoveReversal(models.TransientModel): 'in_receipt': 'out_receipt'} return match.get(move_type) - @api.onchange('move_ids') - def _onchange_move_id(self): - if self.l10n_latam_use_documents: - refund = self.env['account.move'].new({ - 'type': self._reverse_type_map(self.move_ids.type), - 'journal_id': self.move_ids.journal_id.id, - 'partner_id': self.move_ids.partner_id.id, - 'company_id': self.move_ids.company_id.id, - }) - self.l10n_latam_document_type_id = refund.l10n_latam_document_type_id - self.l10n_latam_available_document_type_ids = refund.l10n_latam_available_document_type_ids + @api.depends('move_ids') + def _compute_document_type(self): + self.l10n_latam_available_document_type_ids = False + self.l10n_latam_document_type_id = False + self.l10n_latam_use_documents = False + for record in self: + if len(record.move_ids) > 1: + move_ids_use_document = record.move_ids._origin.filtered(lambda move: move.l10n_latam_use_documents) + if move_ids_use_document: + raise UserError(_('You can only reverse documents with legal invoicing documents from Latin America one at a time.\nProblematic documents: %s') % ", ".join(move_ids_use_document.mapped('name'))) + else: + record.l10n_latam_use_documents = record.move_ids.journal_id.l10n_latam_use_documents + + if record.l10n_latam_use_documents: + refund = record.env['account.move'].new({ + 'type': record._reverse_type_map(record.move_ids.type), + 'journal_id': record.move_ids.journal_id.id, + 'partner_id': record.move_ids.partner_id.id, + 'company_id': record.move_ids.company_id.id, + }) + record.l10n_latam_document_type_id = refund.l10n_latam_document_type_id + record.l10n_latam_available_document_type_ids = refund.l10n_latam_available_document_type_ids def reverse_moves(self): return super(AccountMoveReversal, self.with_context( - default_l10n_latam_document_type_id=self.l10n_latam_document_type_id.id, - default_l10n_latam_document_number=self.l10n_latam_document_number)).reverse_moves() - - @api.depends('l10n_latam_document_type_id') - def _compute_l10n_latam_sequence(self): - for rec in self: - rec.l10n_latam_sequence_id = False - if len(rec.move_ids) <= 1: - refund = rec.env['account.move'].new({ - 'type': self._reverse_type_map(rec.move_ids.type), - 'journal_id': rec.move_ids.journal_id.id, - 'partner_id': rec.move_ids.partner_id.id, - 'company_id': rec.move_ids.company_id.id, - 'l10n_latam_document_type_id': rec.l10n_latam_document_type_id.id, - }) - rec.l10n_latam_sequence_id = refund._get_document_type_sequence() - - @api.onchange('l10n_latam_document_number', 'l10n_latam_document_type_id') - def _onchange_l10n_latam_document_number(self): - if self.l10n_latam_document_type_id: - l10n_latam_document_number = self.l10n_latam_document_type_id._format_document_number( - self.l10n_latam_document_number) - if self.l10n_latam_document_number != l10n_latam_document_number: - self.l10n_latam_document_number = l10n_latam_document_number + default_l10n_latam_document_type_id=self.l10n_latam_document_type_id.id)).reverse_moves() diff --git a/addons/l10n_latam_invoice_document/wizards/account_move_reversal_view.xml b/addons/l10n_latam_invoice_document/wizards/account_move_reversal_view.xml index 9022fbd86ee..f2d8b96527a 100644 --- a/addons/l10n_latam_invoice_document/wizards/account_move_reversal_view.xml +++ b/addons/l10n_latam_invoice_document/wizards/account_move_reversal_view.xml @@ -8,12 +8,10 @@ <field name="arch" type="xml"> <form> <field name="l10n_latam_use_documents" invisible="1"/> - <field name="l10n_latam_sequence_id" invisible="1"/> </form> <field name="date" position="before"> <field name="l10n_latam_available_document_type_ids" invisible="1"/> <field name="l10n_latam_document_type_id" attrs="{'invisible': ['|', ('l10n_latam_use_documents', '=', False), ('refund_method', '=', 'refund')], 'required': [('l10n_latam_use_documents', '=', True), ('refund_method', '!=', 'refund')]}" options="{'no_open': True, 'no_create': True}"/> - <field name="l10n_latam_document_number" attrs="{'invisible': ['|', ('l10n_latam_sequence_id', '!=', False), ('refund_method', '=', 'refund')], 'required': [('l10n_latam_sequence_id', '=', True), ('refund_method', '!=', 'refund')]}"/> </field> </field> </record> |
