-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IMP] l10n_ar_txt_mendoza: TXT Mendoza
Tarea: 38394
- Loading branch information
1 parent
b3cec2c
commit 63439b1
Showing
16 changed files
with
522 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import models | ||
from . import wizard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
'name': 'TXT Mendoza', | ||
'version': "16.0.1.0.0", | ||
'category': 'Accounting', | ||
'author': 'ADHOC SA', | ||
'depends': [ | ||
'l10n_ar_account_tax_settlement', | ||
'l10n_ar_account_withholding', | ||
], | ||
'data': [ | ||
'views/account_move_views.xml', | ||
'views/afip_activity_view.xml', | ||
'views/account_payment_view.xml', | ||
'wizard/res_config_settings_views.xml', | ||
], | ||
'installable': True, | ||
'auto_install': False, | ||
'application': True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from . import account_move | ||
from . import afip_activity | ||
from . import res_company | ||
from . import account_payment_group | ||
from . import account_payment | ||
from . import account_journal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
from odoo import models, fields, _ | ||
from odoo.exceptions import ValidationError, RedirectWarning | ||
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 | ||
""" | ||
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, | ||
}] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from odoo import models, fields, api | ||
|
||
|
||
class AccountMove(models.Model): | ||
_inherit = 'account.move' | ||
|
||
actividades_padron = fields.Many2many( | ||
'afip.activity', | ||
related='partner_id.actividades_padron', | ||
) | ||
activities_mendoza_ids = fields.Many2many( | ||
comodel_name='afip.activity', | ||
string="Activities in Mendoza", | ||
domain="[('id', 'in', actividades_padron)]" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from odoo import models, fields, api | ||
|
||
|
||
class AccountPayment(models.Model): | ||
|
||
_inherit = "account.payment" | ||
|
||
alicuota_mendoza = fields.Float(store=True, readonly=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
############################################################################## | ||
# For copyright and license notices, see __manifest__.py file in module root | ||
# directory | ||
############################################################################## | ||
from odoo import models, api, fields, _ | ||
from odoo.exceptions import ValidationError | ||
|
||
|
||
class AccountPaymentGroup(models.Model): | ||
|
||
_inherit = "account.payment.group" | ||
|
||
# IMPORTANTE: alicuota_mendoza se guarda al momento de correr el código python del impuesto 'Retención IIBB Mendoza Aplicada' --> payment.write({'alicuota_mendoza': alicuota}). Ver por interfaz. | ||
alicuota_mendoza = fields.Float(help="Guardamos la alícuota para el txt de mendoza.", readonly=True) | ||
|
||
def compute_withholdings(self): | ||
"""Para el cálculo de retenciones automáticas de aplicadas de Mendoza siempre tiene que haber una factura vinculada al payment group.""" | ||
tax_group_mendoza_id = self.env.ref('l10n_ar_ux.tax_group_retencion_iibb_za').id | ||
retencion_mdza_aplicada = self.env['account.tax'].with_context(type=None).search([ | ||
('type_tax_use', '=', self.partner_type), | ||
('company_id', '=', self.company_id.id), | ||
('tax_group_id', '=', tax_group_mendoza_id), | ||
], limit=1) | ||
if retencion_mdza_aplicada and not self.to_pay_move_line_ids: | ||
raise ValidationError('No puede calcular retenciones automáticas de aplicadas de Mendoza si no seleccionó una factura para pagar') | ||
else: | ||
super().compute_withholdings() | ||
|
||
# Agregamos la alícuota de mendoza al payment (es necesario para generar el txt iibb_aplicado_sircar_files_values) | ||
payment_mendoza = self.payment_ids.filtered(lambda x: x.tax_withholding_id.tax_group_id.id == tax_group_mendoza_id and x.tax_withholding_id.withholding_type == 'code' and x.state == 'draft') | ||
if payment_mendoza: | ||
payment_mendoza.alicuota_mendoza = self.alicuota_mendoza |
Oops, something went wrong.