Skip to content

Commit

Permalink
[IMP] l10n_ar_account_tax_settlement_mendoza: new module for mendoza …
Browse files Browse the repository at this point in the history
…AR withholdings

Tarea: 38394
X-original-commit: 84ea4e3
  • Loading branch information
pablohmontenegro committed Jan 22, 2025
1 parent ab04800 commit a32e79d
Show file tree
Hide file tree
Showing 19 changed files with 337 additions and 1 deletion.
2 changes: 1 addition & 1 deletion l10n_ar_account_tax_settlement/models/account_journal.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,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 '
Expand Down
2 changes: 2 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
21 changes: 21 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
'name': 'Tax settlement Mendoza',
'version': "16.0.1.0.0",
'category': 'Accounting',
'author': 'ADHOC SA',
'license': 'LGPL-3',
'depends': [
'l10n_ar_account_tax_settlement',
'l10n_ar_withholding_ux',
#'base_import_match',
],
'data': [
'views/account_move_views.xml',
'views/afip_activity_view.xml',
'views/account_payment_view.xml',
'wizard/res_config_settings_views.xml',
],
'installable': False,
'auto_install': False,
'application': False,
}
6 changes: 6 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/__init__.py
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
from . import account_tax
from . import account_journal
27 changes: 27 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/account_journal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from odoo import models, _
from odoo.exceptions import RedirectWarning


class AccountJournal(models.Model):
_inherit = 'account.journal'

def iibb_aplicado_sircar_files_values(self, move_lines):
""" 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.
"""
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)
15 changes: 15 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/account_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from odoo import models, fields


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)]"
)
22 changes: 22 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/account_payment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from odoo import models, fields
from odoo.exceptions import ValidationError


class AccountPayment(models.Model):

_inherit = "account.payment"

# 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. Además debemos guardar en el payment de mendoza la alícuota aplicada. """
res = super().compute_withholdings()
tax_group_mendoza_id = self.env.ref('l10n_ar.tax_group_withholding_vat').id
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:
if 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')
# Agregamos la alícuota de mendoza al payment (es necesario para generar el txt iibb_aplicado_sircar_files_values)
payment_mendoza.alicuota_mendoza = self.alicuota_mendoza
return res
13 changes: 13 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/account_tax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from odoo import models


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 and line.payment_id and line.payment_id.alicuota_mendoza and line.payment_id.tax_withholding_id.codigo_regimen:
return 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})
return super().get_partner_alicuot(partner, date, line=line)
35 changes: 35 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/afip_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from odoo import models, fields
from odoo.exceptions import UserError


class AfipActivity(models.Model):
_inherit = "afip.activity"

alicuota_general = fields.Char()
posee_tasa_cero = fields.Char()
no_posee_certificado_tasa_cero = fields.Char()

def menor_alicuota(self, actividades_con_alicuota_cero):
"""Método utilizado para el cálculo de la menor alícuota a aplicar para 'Retención IIBB Mendoza Aplicada'."""
aliquots = []
activity_codes = self.mapped('code')
activities = self.env['afip.activity'].search([('code', 'in', activity_codes)])
activities_with_aliquots = activities.filtered(lambda x: x.alicuota_general or x.posee_tasa_cero or x.no_posee_certificado_tasa_cero)
if activities and not activities_with_aliquots:
raise UserError('No hay actividades con alícuotas')
actividades_con_alic = activities_with_aliquots.mapped('code')
elementos_no_en_ambas = [activity for activity in activity_codes if activity not in actividades_con_alic]
if elementos_no_en_ambas:
raise UserError('Hay actividades en la factura que no tienen alícuota. Actividades: %s' % (','.join(elementos_no_en_ambas)))
for code in activities_with_aliquots:
if code.alicuota_general:
aliquots.append((code.code, float(code.alicuota_general)))
elif code.posee_tasa_cero and code.code in actividades_con_alicuota_cero:
aliquots.append((code.code, float(code.posee_tasa_cero)))
elif code.no_posee_certificado_tasa_cero:
aliquots.append((code.code, float(code.no_posee_certificado_tasa_cero)))
if not aliquots:
raise UserError('Las actividades incluidas en la factura no tienen alícuota')
# Busco la menor alícuota
min_aliquot = min(aliquots, key=lambda x: x[1])
return min_aliquot
38 changes: 38 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from odoo import models, fields, api
import base64
import csv
from io import StringIO
from odoo.exceptions import UserError


class ResCompany(models.Model):
_inherit = "res.company"

riesgo_fiscal_csv_file = fields.Binary(string="CSV Riesgo Fiscal")
riesgo_fiscal_csv_file_last_update = fields.Datetime(
readonly=True,
)

@api.model
def write(self, vals):
if 'riesgo_fiscal_csv_file' in vals:
vals['riesgo_fiscal_csv_file_last_update'] = fields.Datetime.now()
return super(ResCompany, self).write(vals)

def process_mendoza_csv_file(self, partner_vat, activity_codes):
if self.riesgo_fiscal_csv_file:
# Decode the base64 file content and parse the CSV
csv_content = base64.b64decode(self.riesgo_fiscal_csv_file)
csv_data = StringIO(csv_content.decode('utf-8'))
reader = csv.reader(csv_data, delimiter=';')
actividades_con_riesgo = []
actividades_con_alicuota_cero = []
# Process each row in the CSV
for row in reader:
if partner_vat == row[0] and (row[3] in activity_codes):
if row[6] == 'A':
actividades_con_alicuota_cero.append(row[3])
if row[7] == 'S':
actividades_con_riesgo.append(row[3])
return actividades_con_riesgo, actividades_con_alicuota_cero
raise UserError('Debe subir el archivo de riesgo fiscal en la sección de ajustes de contabilidad para calcular la retención automática de Mendoza.')
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_move_form" model="ir.ui.view">
<field name="name">account.move.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<group id="header_left_group" position="inside">
<field name="actividades_padron" invisible="1"/>
<field name="activities_mendoza_ids" widget="many2many_tags" invisible="move_type not in ['in_invoice', 'in_refund']" readonly="state not in 'draft'"/>
</group>
</field>
</record>
</odoo>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_payment_form" model="ir.ui.view">
<field name="name">account.payment.form</field>
<field name="model">account.payment</field>
<field name="inherit_id" ref="l10n_ar_withholding_ux.view_l10n_ar_payment_withholding_form"/>
<field name="arch" type="xml">
<group name="withholding_data" position="inside">
<field name="alicuota_mendoza" invisible="alicuota_mendoza == 0"/>
</group>
</field>
</record>
</odoo>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<record id="view_afip_activity_form" model="ir.ui.view">
<field name="name">afip.activity.form</field>
<field name="model">afip.activity</field>
<field name="inherit_id" ref="l10n_ar_ux.view_afip_activity_form"/>
<field name="arch" type="xml">
<field name="active" position="after">
<field name='alicuota_general' optional="hide"/>
<field name='posee_tasa_cero' optional="hide"/>
<field name='no_posee_certificado_tasa_cero' optional="hide"/>
</field>
</field>
</record>

<record id="view_afip_activity_tree" model="ir.ui.view">
<field name="name">afip.activity.tree</field>
<field name="model">afip.activity</field>
<field name="inherit_id" ref="l10n_ar_ux.view_afip_activity_tree"/>
<field name="arch" type="xml">
<field name="code" position="after">
<field name='alicuota_general'/>
<field name='posee_tasa_cero'/>
<field name='no_posee_certificado_tasa_cero'/>
</field>
</field>
</record>

</odoo>
5 changes: 5 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import res_config_settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import models, fields

class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

riesgo_fiscal_csv_file = fields.Binary(
related='company_id.riesgo_fiscal_csv_file',
readonly=False,
)
riesgo_fiscal_csv_file_last_update = fields.Datetime(
related='company_id.riesgo_fiscal_csv_file_last_update',
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<record model="ir.ui.view" id="res_config_settings_view_form">
<field name="name">res.config.settings.view.form.inherit.l10n_ar_afip_ws</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="l10n_ar.res_config_settings_view_form"/>
<field name="arch" type="xml">
<block id="argentina_localization" position="inside">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<label for="riesgo_fiscal_csv_file" string="Riesgo Fiscal"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
<div class="text-muted">
Agregar archivo csv de Riesgo Fiscal:
</div>
<div class="content-group">
<div class="row">
<field name="riesgo_fiscal_csv_file"/>
</div>
</div>
<div class="row">
<label for="riesgo_fiscal_csv_file_last_update" string="Última Modificación"/>
<field name="riesgo_fiscal_csv_file_last_update" class="o_inline"/>
</div>
</div>
</div>
</block>
</field>
</record>

</odoo>
5 changes: 5 additions & 0 deletions l10n_ar_account_tax_settlement_mendoza/wizards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import res_config_settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import models, fields

class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

riesgo_fiscal_csv_file = fields.Binary(
related='company_id.riesgo_fiscal_csv_file',
readonly=False,
)
riesgo_fiscal_csv_file_last_update = fields.Datetime(
related='company_id.riesgo_fiscal_csv_file_last_update',
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<record model="ir.ui.view" id="res_config_settings_view_form">
<field name="name">res.config.settings.view.form.inherit.l10n_ar_afip_ws</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="l10n_ar.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div id="argentina_localization" position="inside">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<label for="riesgo_fiscal_csv_file" string="Riesgo Fiscal"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
<div class="text-muted">
Agregar archivo csv de Riesgo Fiscal:
</div>
<div class="content-group">
<div class="row">
<field name="riesgo_fiscal_csv_file"/>
</div>
</div>
<div class="row">
<label for="riesgo_fiscal_csv_file_last_update" string="Última Modificación"/>
<field name="riesgo_fiscal_csv_file_last_update" class="o_inline"/>
</div>
</div>
</div>
</div>
</field>
</record>

</odoo>

0 comments on commit a32e79d

Please sign in to comment.