diff options
Diffstat (limited to 'addons/l10n_ar/models/account_journal.py')
| -rw-r--r-- | addons/l10n_ar/models/account_journal.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/addons/l10n_ar/models/account_journal.py b/addons/l10n_ar/models/account_journal.py new file mode 100644 index 00000000..113f2f24 --- /dev/null +++ b/addons/l10n_ar/models/account_journal.py @@ -0,0 +1,139 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api, _ +from odoo.exceptions import ValidationError, RedirectWarning + + +class AccountJournal(models.Model): + + _inherit = "account.journal" + + l10n_ar_afip_pos_system = fields.Selection( + selection='_get_l10n_ar_afip_pos_types_selection', string='AFIP POS System') + l10n_ar_afip_pos_number = fields.Integer( + 'AFIP POS Number', help='This is the point of sale number assigned by AFIP in order to generate invoices') + company_partner = fields.Many2one('res.partner', related='company_id.partner_id') + l10n_ar_afip_pos_partner_id = fields.Many2one( + 'res.partner', 'AFIP POS Address', help='This is the address used for invoice reports of this POS', + domain="['|', ('id', '=', company_partner), '&', ('id', 'child_of', company_partner), ('type', '!=', 'contact')]" + ) + l10n_ar_share_sequences = fields.Boolean( + 'Unified Book', help='Use same sequence for documents with the same letter') + + def _get_l10n_ar_afip_pos_types_selection(self): + """ Return the list of values of the selection field. """ + return [ + ('II_IM', _('Pre-printed Invoice')), + ('RLI_RLM', _('Online Invoice')), + ('BFERCEL', _('Electronic Fiscal Bond - Online Invoice')), + ('FEERCELP', _('Export Voucher - Billing Plus')), + ('FEERCEL', _('Export Voucher - Online Invoice')), + ('CPERCEL', _('Product Coding - Online Voucher')), + ] + + def _get_journal_letter(self, counterpart_partner=False): + """ Regarding the AFIP responsibility of the company and the type of journal (sale/purchase), get the allowed + letters. Optionally, receive the counterpart partner (customer/supplier) and get the allowed letters to work + with him. This method is used to populate document types on journals and also to filter document types on + specific invoices to/from customer/supplier + """ + self.ensure_one() + letters_data = { + 'issued': { + '1': ['A', 'B', 'E', 'M'], + '3': [], + '4': ['C'], + '5': [], + '6': ['C', 'E'], + '9': ['I'], + '10': [], + '13': ['C', 'E'], + '99': [] + }, + 'received': { + '1': ['A', 'B', 'C', 'M', 'I'], + '3': ['B', 'C', 'I'], + '4': ['B', 'C', 'I'], + '5': ['B', 'C', 'I'], + '6': ['A', 'B', 'C', 'I'], + '9': ['E'], + '10': ['E'], + '13': ['A', 'B', 'C', 'I'], + '99': ['B', 'C', 'I'] + }, + } + if not self.company_id.l10n_ar_afip_responsibility_type_id: + action = self.env.ref('base.action_res_company_form') + msg = _('Can not create chart of account until you configure your company AFIP Responsibility and VAT.') + raise RedirectWarning(msg, action.id, _('Go to Companies')) + + letters = letters_data['issued' if self.type == 'sale' else 'received'][ + self.company_id.l10n_ar_afip_responsibility_type_id.code] + if counterpart_partner: + counterpart_letters = letters_data['issued' if self.type == 'purchase' else 'received'].get( + counterpart_partner.l10n_ar_afip_responsibility_type_id.code, []) + letters = list(set(letters) & set(counterpart_letters)) + return letters + + def _get_journal_codes(self): + self.ensure_one() + usual_codes = ['1', '2', '3', '6', '7', '8', '11', '12', '13'] + mipyme_codes = ['201', '202', '203', '206', '207', '208', '211', '212', '213'] + invoice_m_code = ['51', '52', '53'] + receipt_m_code = ['54'] + receipt_codes = ['4', '9', '15'] + expo_codes = ['19', '20', '21'] + liq_product_codes = ['60', '61'] + if self.type != 'sale': + return [] + elif self.l10n_ar_afip_pos_system == 'II_IM': + # pre-printed invoice + return usual_codes + receipt_codes + expo_codes + invoice_m_code + receipt_m_code + elif self.l10n_ar_afip_pos_system in ['RAW_MAW', 'RLI_RLM']: + # electronic/online invoice + return usual_codes + receipt_codes + invoice_m_code + receipt_m_code + mipyme_codes + liq_product_codes + elif self.l10n_ar_afip_pos_system in ['CPERCEL', 'CPEWS']: + # invoice with detail + return usual_codes + invoice_m_code + elif self.l10n_ar_afip_pos_system in ['BFERCEL', 'BFEWS']: + # Bonds invoice + return usual_codes + mipyme_codes + elif self.l10n_ar_afip_pos_system in ['FEERCEL', 'FEEWS', 'FEERCELP']: + return expo_codes + + @api.constrains('type', 'l10n_ar_afip_pos_system', 'l10n_ar_afip_pos_number', 'l10n_ar_share_sequences', + 'l10n_latam_use_documents') + def _check_afip_configurations(self): + """ Do not let the user update the journal if it already contains confirmed invoices """ + journals = self.filtered(lambda x: x.company_id.country_id.code == "AR" and x.type in ['sale', 'purchase']) + invoices = self.env['account.move'].search([('journal_id', 'in', journals.ids), ('posted_before', '=', True)], limit=1) + if invoices: + raise ValidationError( + _("You can not change the journal's configuration if it already has validated invoices") + ' (' + + ', '.join(invoices.mapped('journal_id').mapped('name')) + ')') + + @api.constrains('l10n_ar_afip_pos_number') + def _check_afip_pos_number(self): + to_review = self.filtered( + lambda x: x.type == 'sale' and x.l10n_latam_use_documents and + x.company_id.country_id.code == "AR") + + if to_review.filtered(lambda x: x.l10n_ar_afip_pos_number == 0): + raise ValidationError(_('Please define an AFIP POS number')) + + if to_review.filtered(lambda x: x.l10n_ar_afip_pos_number > 99999): + raise ValidationError(_('Please define a valid AFIP POS number (5 digits max)')) + + @api.onchange('l10n_ar_afip_pos_system') + def _onchange_l10n_ar_afip_pos_system(self): + """ On 'Pre-printed Invoice' the usual is to share sequences. On other types, do not share """ + self.l10n_ar_share_sequences = bool(self.l10n_ar_afip_pos_system == 'II_IM') + + @api.onchange('l10n_ar_afip_pos_number', 'type') + def _onchange_set_short_name(self): + """ Will define the AFIP POS Address field domain taking into account the company configured in the journal + The short code of the journal only admit 5 characters, so depending on the size of the pos_number (also max 5) + we add or not a prefix to identify sales journal. + """ + if self.type == 'sale' and self.l10n_ar_afip_pos_number: + self.code = "%05i" % self.l10n_ar_afip_pos_number |
