diff --git a/l10n_ar_account_tax_settlement/models/account_journal.py b/l10n_ar_account_tax_settlement/models/account_journal.py index 999b23fb..ed5c5dac 100644 --- a/l10n_ar_account_tax_settlement/models/account_journal.py +++ b/l10n_ar_account_tax_settlement/models/account_journal.py @@ -853,7 +853,7 @@ def iibb_aplicado_sircar_files_values(self, move_lines): line_nbr = 1 for line in move_lines.filtered('payment_id'): alicuot_line = line.tax_line_id.get_partner_alicuot( - line.partner_id, line.date) + line.partner_id, line.date, line) if not alicuot_line: raise ValidationError(_( 'No hay alicuota configurada en el partner ' diff --git a/l10n_ar_txt_mendoza/__manifest__.py b/l10n_ar_txt_mendoza/__manifest__.py index 80289292..53362ed1 100644 --- a/l10n_ar_txt_mendoza/__manifest__.py +++ b/l10n_ar_txt_mendoza/__manifest__.py @@ -15,5 +15,5 @@ ], 'installable': True, 'auto_install': False, - 'application': True, + 'application': False, } diff --git a/l10n_ar_txt_mendoza/models/__init__.py b/l10n_ar_txt_mendoza/models/__init__.py index fbf93f5c..666298f9 100644 --- a/l10n_ar_txt_mendoza/models/__init__.py +++ b/l10n_ar_txt_mendoza/models/__init__.py @@ -3,4 +3,5 @@ from . import res_company from . import account_payment_group from . import account_payment +from . import account_tax from . import account_journal diff --git a/l10n_ar_txt_mendoza/models/account_journal.py b/l10n_ar_txt_mendoza/models/account_journal.py index f79078d7..adede83c 100644 --- a/l10n_ar_txt_mendoza/models/account_journal.py +++ b/l10n_ar_txt_mendoza/models/account_journal.py @@ -1,252 +1,30 @@ -from odoo import models, fields, _ +from odoo import models, fields, api, _ from odoo.exceptions import ValidationError, RedirectWarning +from odoo.tools.float_utils import float_round +# from odoo.tools.misc import formatLang +# from odoo.tools import DEFAULT_SERVER_DATE_FORMAT import re -######### -# helpers -######### - - -def format_amount(amount, padding=15, decimals=2, sep=""): - if amount < 0: - template = "-{:0>%dd}" % (padding - 1 - len(sep)) - else: - template = "{:0>%dd}" % (padding - len(sep)) - res = template.format( - int(round(abs(amount) * 10**decimals, decimals))) - if sep: - res = "{0}{1}{2}".format(res[:-decimals], sep, res[-decimals:]) - return res - - -def get_line_tax_base(move_line): - return sum(move_line.move_id.line_ids.filtered( - lambda x: move_line.tax_line_id in x.tax_ids).mapped( - 'balance')) - - -def get_pos_and_number(full_number): - """ - Para un numero nos fijamos si hay '-', si hay: - * mas de 1, entonces devolvemos error - * 1, entonces devolvemos las partes (solo parte númerica) - * 0, entonces devolvemos '0' y parte númerica del número que se pasó - """ - args = full_number.split('-') - if len(args) == 1: - # si no hay '-' tomamos punto de venta 0 - return ('0', re.sub('[^0-9]', '', args[0])) - else: - return re.sub('[^0-9]', '', args[0]), re.sub('[^0-9]', '', ''.join(args[1:])) - - class AccountJournal(models.Model): _inherit = 'account.journal' def iibb_aplicado_sircar_files_values(self, move_lines): - """ Especificacion en /doc/sircar, solicitado en ticket 62526. Método heredado de https://github.com/ingadhoc/odoo-argentina-ee/blob/16.0/l10n_ar_account_tax_settlement/models/account_journal.py#L840 + """ Extendemos este método del original de l10n_ar_account_tax_settlement para mendoza. El objetivo de este método es validar que el impuesto de mendoza tenga código de régimen. """ - self.ensure_one() - ret = '' - perc = '' - - for line in move_lines.filtered( - lambda x: not x.payment_id and not x.move_id): - raise ValidationError(_( - 'Hay lineas a liquidar que no estan enlazadas a pagos ni ' - 'facturas lo cual es requerido para generar el TXT')) - - line_nbr = 1 - for line in move_lines.filtered('payment_id'): - alicuot_line = line.tax_line_id.get_partner_alicuot( - line.partner_id, line.date) if not line.tax_line_id.withholding_type == 'code' else line.payment_id.alicuota_mendoza * 100 - - if not isinstance(alicuot_line, float) and not alicuot_line: - raise ValidationError(_( - 'No hay alicuota configurada en el partner ' - '"%s" (id: %s)') % ( - line.partner_id.name, line.partner_id.id)) - - payment = line.payment_id - internal_type = line.l10n_latam_document_type_id.internal_type - - # 1 Número de Renglón (único por archivo) - content = [] - content.append('%05d' % line_nbr) - - # 2 Origen del Comprobante - content.append('1') - - # 3 Tipo del Comprobante - if payment.payment_type == 'outbound': - content.append('1') - else: - content.append('2') - - # 4 Número del comprobante - content.append('%012d' % int( - re.sub('[^0-9]', '', line.payment_id.withholding_number or ''))) - - # 5 Cuit del contribuyene - content.append(line.partner_id.ensure_vat()) - - # 6 Fecha de la percepción - content.append( - fields.Date.from_string(line.date).strftime('%d/%m/%Y')) - - # 7 Monto sujeto a percepción - content.append(format_amount( - payment.withholdable_base_amount, 12, 2, '.')) - - # 8 alicuota de la retencion - content.append(format_amount( - alicuot_line.alicuota_retencion if not isinstance(alicuot_line, float) else alicuot_line, 6, 2, '.')) - - # 9 Monto retenido - content.append(format_amount(-line.balance, 12, 2, '.')) - - # 10 Tipo de Régimen de Percepción - # (código correspondiente según tabla definida por la jurisdicción) - if not isinstance(alicuot_line, float) and not alicuot_line.regimen_retencion: - raise ValidationError(_( - 'No hay regimen de retencion configurado para la alícuota' - ' del partner %s') % line.partner_id.name) - elif not line.tax_line_id.codigo_regimen: - raise RedirectWarning( - message=_("El impuesto '%s' not tiene código de regimen en solapa 'Opciones avanzadas' campo 'Codigo de regimen'.", line.tax_line_id.name), - action={ - 'type': 'ir.actions.act_window', - 'res_model': 'account.tax', - 'views': [(False, 'form')], - 'res_id': line.tax_line_id.id, - 'name': _('Tax'), - 'view_mode': 'form', - }, - button_text=_('Editar Impuesto'), - ) - content.append(alicuot_line.regimen_retencion if not isinstance(alicuot_line, float) else line.tax_line_id.codigo_regimen) - - # 11 Jurisdicción: código en Convenio Multilateral de la - # jurisdicción a la cual está presentando la DDJJ - if not line.tax_line_id.jurisdiction_code: - raise ValidationError(_( - 'No hay etiqueta de jurisdicción configurada!')) - - content.append(line.tax_line_id.jurisdiction_code) - - # Tipo registro 2. Provincia Cordoba - if line.tax_line_id.jurisdiction_code in ['904', '914']: - - # 12 Tipo de Operación (1-Efectuada, 2-Anulada, 3-Omitida) - content.append('2' if internal_type == 'credit_note' else '1') - - # 13 Fecha de Emisión de Constancia (en formato dd/mm/aaaa) - content.append(fields.Date.from_string(line.date).strftime('%d/%m/%Y')) - - # 14 Número de Constancia - Numeric(14) - content.append('%014s' % int(re.sub('[^0-9]', '', payment.withholding_number or '0')[:14])) - - # 15 Número de Constancia original (sólo para las Anulaciones –ver códigos por jur-) - Numeric(14) - original_invoice = line.move_id._found_related_invoice() or line.move_id - content.append('%014d' % int(re.sub('[^0-9]', '', original_invoice.document_number or '')) - if internal_type == 'credit_note' else '%014d' % 0) - - ret += ','.join(content) + '\r\n' - line_nbr += 1 - - line_nbr = 1 - for line in move_lines.filtered(lambda x: x.move_id.is_invoice()): - alicuot_line = line.tax_line_id.get_partner_alicuot( - line.partner_id, line.date) - if not alicuot_line: - raise ValidationError(_( - 'No hay alicuota configurada en el partner ' - '"%s" (id: %s)') % ( - line.partner_id.name, line.partner_id.id)) - - - # 1 Número de Renglón (único por archivo) - content = [] - content.append('%05d' % line_nbr) - - letter = line.l10n_latam_document_type_id.l10n_ar_letter - - # 2 Tipo de comprobante - internal_type = line.l10n_latam_document_type_id.internal_type - if internal_type == 'invoice': - tipo_comprobante = letter == 'E' and 5 or 1 - elif internal_type == 'credit_note': - tipo_comprobante = letter == 'E' and 106 or 102 - elif internal_type == 'debit_note': - tipo_comprobante = letter == 'E' and 6 or 2 - elif line.move_id.type == 'out_invoice': - tipo_comprobante = 20 - elif line.move_id.type == 'out_refund': - tipo_comprobante = 120 - else: - raise ValidationError(_('Tipo de comprobante no reconocido')) - content.append('%03d' % tipo_comprobante) - - # 3 Letra del comprobante - content.append(line.l10n_latam_document_type_id.l10n_ar_letter) - - # 4 Número del comprobante - content.append('%012d' % int( - re.sub('[^0-9]', '', line.move_id.l10n_latam_document_number or ''))) - - # 5 Cuit del contribuyene - content.append(line.partner_id.ensure_vat()) - - # 6 Fecha de la percepción - content.append( - fields.Date.from_string(line.date).strftime('%d/%m/%Y')) - - # 7 Monto sujeto a percepción - content.append(format_amount(-get_line_tax_base(line), 12, 2, '.')) - - # 8 alicuota de la percepcion - content.append(format_amount( - alicuot_line.alicuota_percepcion, 6, 2, '.')) - - # 9 Monto percibido - content.append(format_amount(-line.balance, 12, 2, '.')) - - # 10 Tipo de Régimen de Percepción - # (código correspondiente según tabla definida por la jurisdicción) - if not alicuot_line.regimen_percepcion: - raise ValidationError(_( - 'No hay regimen de percepcion configurado para la alícuota' - ' del partner %s') % line.partner_id.name) - content.append(alicuot_line.regimen_percepcion) - - # 11 Jurisdicción: código en Convenio Multilateral de la - # jurisdicción a la cual está presentando la DDJJ - if not line.tax_line_id.jurisdiction_code: - raise ValidationError(_( - 'No hay etiqueta de jurisdicción configurada!')) - - content.append(line.tax_line_id.jurisdiction_code) - - # Tipo registro 2. Provincia Cordoba - if line.tax_line_id.jurisdiction_code in ['904', '914']: - - # 12 Tipo de Operación (1-Efectuada, 2-Anulada, 3-Omitida, 4-Informativa) - content.append('2' if internal_type == 'credit_note' else '1') - - # 13 Número de Constancia original (sólo para 2-Anulaciones) Alfanumérico (14) - ejemplo 1A002311312221 - content.append(self._get_perception_original_invoice_number(line) - if internal_type == 'credit_note' else '%014d' % 0) - - perc += ','.join(content) + '\r\n' - line_nbr += 1 - - return [ - { - 'txt_filename': 'Perc IIBB Aplicadas para SIRCAR.txt', - 'txt_content': perc, - }, - { - 'txt_filename': 'Ret IIBB Aplicadas para SIRCAR.txt', - 'txt_content': ret, - }] - + tax_group_id_mendoza_id = self.env.ref('l10n_ar_ux.tax_group_retencion_iibb_za') + mendoza_lines = move_lines.filtered(lambda x: x.payment_id and x.tax_line_id.withholding_type == 'code' and x.tax_group_id == tax_group_id_mendoza_id) + missing_codigo_regimen = mendoza_lines.filtered(lambda x: not x.payment_id.tax_withholding_id.codigo_regimen) + if mendoza_lines and missing_codigo_regimen: + raise RedirectWarning( + message=_("El impuesto '%s' not tiene código de regimen en solapa 'Opciones avanzadas' campo 'Codigo de regimen'.", missing_codigo_regimen.payment_id.tax_withholding_id.name), + action={ + 'type': 'ir.actions.act_window', + 'res_model': 'account.tax', + 'views': [(False, 'form')], + 'res_id': mendoza_lines.tax_line_id.id, + 'name': _('Tax'), + 'view_mode': 'form', + }, + button_text=_('Editar Impuesto'), + ) + return super().iibb_aplicado_sircar_files_values(move_lines) diff --git a/l10n_ar_txt_mendoza/models/account_tax.py b/l10n_ar_txt_mendoza/models/account_tax.py new file mode 100644 index 00000000..0d48e4aa --- /dev/null +++ b/l10n_ar_txt_mendoza/models/account_tax.py @@ -0,0 +1,15 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import UserError +from dateutil.relativedelta import relativedelta + + +class AccountTax(models.Model): + _inherit = "account.tax" + + def get_partner_alicuot(self, partner, date, line=None): + """ La alícuota para el archivo txt de mendoza que se genera desde el método iibb_aplicado_sircar_files_values no se obtiene del partner sino que se obtiene del payment, y el código de régimen se obtiene del impuesto pero extendemos el método get_partner_alicuot original para usarlo como puente, agregamos 'line' como parámentro. """ + if line.payment_id.alicuota_mendoza and line.payment_id.tax_withholding_id.codigo_regimen: + aliquot = self.env['res.partner.arba_alicuot'].new({'alicuota_retencion': line.payment_id.alicuota_mendoza * 100, 'partner_id': partner, 'regimen_retencion': line.payment_id.tax_withholding_id.codigo_regimen}) + else: + aliquot = super().get_partner_alicuot(partner, date) + return aliquot