Skip to content

Commit

Permalink
[MIG] l10n_uy_reports: Migration to 18.0
Browse files Browse the repository at this point in the history
  • Loading branch information
docker-odoo authored and jue-adhoc committed Dec 23, 2024
1 parent 599060c commit 5a99a74
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 62 deletions.
6 changes: 3 additions & 3 deletions l10n_uy_reports/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
Uruguay - Accounting Reports
============================

* Agrega la posibilidad de ver/exportar xls con el libro de IVA Compras/Ventas Uruguayo, esto en el menu "Tax Reports"
* Agrega el menu Resumen de IVA para uruguay, reporte que se puee usar para analizar los datos de facturacióneed
* Agrega la posibilidad de ver/exportar xls con el libro de IVA Compras/Ventas Uruguayo en el menu "Tax Return"
* Agrega el menú Resumen de IVA para Uruguay, reporte que se puede usar para analizar los datos de facturación
* Nuevo asistente que permite generar los archivos TXT para presentar el Formulario 2/181 (hasta el momento solo repota impuestos de iva compra/venta). Instructivos: https://www.gub.uy/direccion-general-impositiva/comunicacion/publicaciones/instructivo-para-confeccion-presentacion-declaraciones-aplicacion-beta y https://www.gub.uy/direccion-general-impositiva/comunicacion/publicaciones/informacion-sobre-formulario-2181


Expand All @@ -25,7 +25,7 @@ Detalle de implementacion
* Detalle completo aplicativo B https://www.gub.uy/direccion-general-impositiva/politicas-y-gestion/aplicacion-beta-version-990
* Especificacion de formularios https://www.gub.uy/direccion-general-impositiva/comunicacion/publicaciones/instructivo-para-confeccion-presentacion-declaraciones-beta
* Agentes de Informacion https://www.gub.uy/direccion-general-impositiva/sites/direccion-general-impositiva/files/documentos/publicaciones/Agentes%20de%20informaci%C3%B3n.%20Cuadro%20formulario%202181_1.pdf
* Reference contacts:
* Contactos de referencia:
- Telefónicas: 1344 opción 5 (21344 desde el interior del país).
- Correo electrónico: [email protected] o a través del servicio Consultas Web ("restantes impuestos")
- Por incidentes informáticos: SAC - Registro de Incidentes
Expand Down
4 changes: 2 additions & 2 deletions l10n_uy_reports/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Uruguay - Accounting Reports',
'version': "17.0.1.0.0",
'version': "18.0.1.0.0",
'author': 'ADHOC SA',
'license': 'LGPL-3',
'category': 'Localization',
Expand All @@ -23,5 +23,5 @@
],
},
'auto_install': True,
'installable': False,
'installable': True,
}
1 change: 0 additions & 1 deletion l10n_uy_reports/data/account_financial_report_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<field name="load_more_limit" eval="80"/>
<field name="column_ids">
<record id="l10n_uy_vat_book_report_column_invoice_date" model="account.report.column">
<!-- TODO revisar que realmente es el campo invoice_date y no el campo date -->
<field name="name">Date</field>
<field name="expression_label">date</field>
<field name="figure_type">date</field>
Expand Down
24 changes: 11 additions & 13 deletions l10n_uy_reports/models/l10n_uy_vat_book.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _

from odoo.tools import SQL

class UruguayanReportCustomHandler(models.AbstractModel):
_name = 'l10n_uy.tax.report.handler'
_inherit = 'account.generic.tax.report.handler'
_inherit = 'account.tax.report.handler'
_description = 'Uruguayan Report Custom Handler'

def _get_custom_display_config(self):
Expand All @@ -26,17 +26,16 @@ def _dynamic_lines_generator(self, report, options, all_column_groups_expression

# Build full query
query_list = []
full_query_params = []
for column_group_key, column_group_options in report._split_options_per_column_group(options).items():
query, params = self._build_query(report, column_group_options, column_group_key)
query_list.append(f"({query})")
full_query_params += params
options_per_col_group = report._split_options_per_column_group(options)
for column_group_key, column_group_options in options_per_col_group.items():
query = self._build_query(report, column_group_options, column_group_key)
query_list.append(SQL("(%s)", query))

# Set defaults here since the results of the query for this column_group_key might be empty
total_values_dict.setdefault(column_group_key, dict.fromkeys(number_keys, 0.0))

full_query = " UNION ALL ".join(query_list)
self._cr.execute(full_query, full_query_params)
full_query = SQL(" UNION ALL ").join(query_list)
self._cr.execute(full_query)
results = self._cr.dictfetchall()
for result in results:
# Iterate over these results in order to fill the move_info_dict dictionary
Expand Down Expand Up @@ -91,12 +90,11 @@ def _custom_options_initializer(self, report, options, previous_options=None):
####################################################

def _build_query(self, report, options, column_group_key):
tables, where_clause, where_params = report._query_get(options, 'strict_range')
query = report._get_report_query(options, 'strict_range')

where_clause = f"AND {where_clause}"
tax_types = tuple(self._vat_book_get_selected_tax_types(options))

return self.env['account.uy.vat.line']._uy_vat_line_build_query(tables, where_clause, where_params, column_group_key, tax_types)
return self.env['account.uy.vat.line']._uy_vat_line_build_query(query.from_clause, query.where_clause, column_group_key, tax_types)

def _create_report_line(self, report, options, move_vals, move_id, number_values):
""" Create a standard (non total) line for the report
Expand Down
36 changes: 22 additions & 14 deletions l10n_uy_reports/report/account_uy_vat_line.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, tools
from odoo.tools import SQL


class AccountUyVatLine(models.Model):
Expand Down Expand Up @@ -57,24 +58,26 @@ def init(self):
# we use tax_ids for base amount instead of tax_base_amount for two reasons:
# * zero taxes do not create any aml line so we can't get base for them with tax_base_amount
# * we use same method as in odoo tax report to avoid any possible discrepancy with the computed tax_base_amount
query, params = self._uy_vat_line_build_query()
sql = f"""CREATE or REPLACE VIEW account_uy_vat_line as ({query})"""
cr.execute(sql, params)
query = self._uy_vat_line_build_query()
sql = SQL("""CREATE or REPLACE VIEW account_uy_vat_line as (%s)""", query)
cr.execute(sql)

@api.model
def _uy_vat_line_build_query(self, tables='account_move_line', where_clause='', where_params=None,
def _uy_vat_line_build_query(self, table_references=None, search_condition=None,
column_group_key='', tax_types=('sale', 'purchase')):
"""Returns the SQL Select query fetching account_move_lines info in order to build the pivot view for the VAT summary.
This method is also meant to be used outside this model, which is the reason why it gives the opportunity to
provide a few parameters, for which the defaults are used in this model.
The query is used to build the VAT book report"""
if where_params is None:
where_params = []
if table_references is None:
table_references = SQL('account_move_line')
search_condition = SQL('AND (%s)', search_condition) if search_condition else SQL()

query = f"""
query = SQL(
"""
SELECT
%s AS column_group_key,
%(column_group_key)s AS column_group_key,
account_move.id,
(CASE WHEN lit.l10n_uy_dgi_code = '2' THEN rp.vat ELSE NULL END) AS rut,
account_move.name as move_name,
Expand All @@ -98,7 +101,7 @@ def _uy_vat_line_build_query(self, tables='account_move_line', where_clause='',
SUM(CASE WHEN nt.amount not in (22.0, 10.0, 0.0) AND nt.l10n_uy_tax_category = 'vat' THEN account_move_line.balance ELSE 0 END) AS other_taxes,
SUM(account_move_line.balance) AS total
FROM
{tables}
%(table_references)s
JOIN
account_move ON account_move_line.move_id = account_move.id
LEFT JOIN
Expand All @@ -116,11 +119,16 @@ def _uy_vat_line_build_query(self, tables='account_move_line', where_clause='',
WHERE
(account_move_line.tax_line_id is not NULL OR bt.amount IN (22.0, 10.0, 0.0) AND bt.l10n_uy_tax_category = 'vat') AND
account_move.move_type IN ('out_invoice', 'in_invoice', 'out_refund', 'in_refund')
AND (nt.type_tax_use in %s OR bt.type_tax_use in %s)
{where_clause}
AND (nt.type_tax_use in %(tax_types)s OR bt.type_tax_use in %(tax_types)s)
%(search_condition)s
GROUP BY
account_move.id, rp.id, lit.id, tax_type
ORDER BY
account_move.date, account_move.name"""

return query, [column_group_key, tax_types, tax_types, *where_params]
account_move.invoice_date, account_move.name
""",
column_group_key=column_group_key,
table_references=table_references,
tax_types=tax_types,
search_condition=search_condition,
)
return query
8 changes: 4 additions & 4 deletions l10n_uy_reports/report/account_uy_vat_line_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
</record>

<record id="view_account_uy_vat_line_tree" model="ir.ui.view">
<field name="name">account.uy.vat.line.tree</field>
<field name="name">account.uy.vat.line.list</field>
<field name="model">account.uy.vat.line</field>
<field name="arch" type="xml">
<tree editable="bottom">
<list editable="bottom">
<field name="date"/>
<field name="move_id"/>
<field name="partner_id"/>
Expand All @@ -46,7 +46,7 @@
<field name="other_taxes" sum="Total"/>
<field name="total" sum="Total"/>
<button name="open_journal_entry" string="Open" type="object" icon="fa-external-link" help="Open journal entry"/>
</tree>
</list>
</field>
</record>

Expand All @@ -70,7 +70,7 @@
<record id="action_account_uy_vat_line" model="ir.actions.act_window">
<field name="name">VAT Summary</field>
<field name="res_model">account.uy.vat.line</field>
<field name="view_mode">pivot,tree</field>
<field name="view_mode">pivot,list</field>
<field name="context">{'search_default_posted': 1, 'time_ranges': {'field': 'date', 'range': 'last_month'}}</field>
</record>

Expand Down
50 changes: 25 additions & 25 deletions l10n_uy_reports/wizards/form_report_wiz.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import base64
import json
import logging
from odoo import models, api, fields, _
from odoo.exceptions import UserError
Expand Down Expand Up @@ -80,18 +79,20 @@ def _search_tax(self, tax_amount, tax_type):
return res

def _get_form_2181_data(self):
""" Prepara the content of the file
"""
Prepara the content of the file
Este es un solo archivo TXT el cual contiene.
En el Rubro 5 se ingresan agrupados por Identificación del contribuyente y número de línea
correspondiente al concepto declarado e importe.
Agrupado por partner, por periodo y fecha de factura la información de los impuestos generados
return the string with the lines of the file to write """
Devuelve un string con las lineas de la carpeta a escribir
"""
lines = []

# Importante. aca este el archivo generado mezcla iva compras e iva ventas.
# Importante: el archivo generado mezcla iva compras e iva ventas.
line_code = {
self._search_tax(22.0, 'sale'): '502', # 502 IVA Ventas Tasa Básica a Contribuyentes
self._search_tax(10.0, 'sale'): '503', # 503 IVA Ventas Tasa Mínima a Contribuyentes
Expand Down Expand Up @@ -142,24 +143,23 @@ def _get_form_2181_data(self):
for rut_partner, invoices in data.items():
amount_total = {}
for inv in invoices:
group_by_subtotal_values = list(inv.tax_totals.get('groups_by_subtotal').values())[0] if list(inv.tax_totals.get('groups_by_subtotal').values()) else []
for item in group_by_subtotal_values:
tax_group_id = item.get('tax_group_id')
if tax_group_id in taxes_group_ids:
# los comprobantes exentos tienen 0.0 en tax_group_amount, entonces tomamos tax_group_base_amount
inv_amount = item.get('tax_group_amount') if not tax_group_id == self.env.ref('l10n_uy_account.tax_group_vat_exempt').id else item.get('tax_group_base_amount')
# No estaba ene especifcacion pero vimos via un ejemplo que los montos reportados siempre son en
# pesos. aun qu el comprobamte sea de otra moneda, es por eso que hacemos esta conversion
if inv.currency_id != UYU_currency:
inv_amount = inv_amount * (inv.l10n_uy_currency_rate or (inv.currency_id._convert(1.0, inv.company_id.currency_id, inv.company_id, inv.date, round=False)))
key = (tax_group_id, 'sale' if 'out_' in inv.move_type else 'purchase')
sing = '+' if inv.move_type in ['out_invoice', 'in_invoice', 'out_receipt', 'in_receipt'] else '-'
if sing == '+':
amount_total[key] = amount_total.get(key, 0.0) + (amount_total.get(tax_group_id, 0.0)) + inv_amount
else:
amount_total[key] = amount_total.get(key, 0.0) + (amount_total.get(tax_group_id, 0.0)) - inv_amount
for tax in amount_total:
subtotals = inv.tax_totals.get('subtotals', [])
currency_is_uyu = inv.currency_id == UYU_currency
is_sale = 'out_' in inv.move_type
sign = 1 if inv.move_type in ['out_invoice', 'in_invoice', 'out_receipt', 'in_receipt'] else -1

for item in subtotals:
tax_group_ids = item.get('tax_groups', [])
# No estaba ene especifcacion pero vimos via un ejemplo que los montos reportados siempre son en
# pesos, aunque el comprobamte sea de otra moneda, es por eso que utilizamos el monto convertido
tax_amount = item.get('tax_amount') if currency_is_uyu else item.get('tax_amount_currency')
for tax_group_id in tax_group_ids:
tax_id = tax_group_id['id']
if tax_id in taxes_group_ids:
key = (tax_id, 'sale' if is_sale else 'purchase')
amount_total[key] = amount_total.get(key, 0.0) + (sign * tax_amount)

for tax in amount_total:
if not tax_code.get(tax):
continue

Expand All @@ -172,13 +172,13 @@ def _get_form_2181_data(self):
# Campo 2 - Formulario. Num 5
content_data += "{: 5d};".format(int(self.uy_form_id))

# Campo 3 - Período (AAAAMM) Num 6. Ejemplo: 200306
# Campo 3 - Período (AAAAMM) Num 6. Ejemplo: 202406
content_data += "{};".format(self.date_period)

# Campo 4 - RUT Informado. Num 12
content_data += rut_partner.zfill(12) + ";"

# Campo 5 - Factura AAAAMM Num 6. Ejemplo: 200305
# Campo 5 - Factura AAAAMM Num 6. Ejemplo: 202405
content_data += "{};".format(line.move_id.date.strftime("%Y%m"))

# Campo 6 - Línea del Rubro 5 del Formulario
Expand All @@ -199,7 +199,7 @@ def action_get_files(self):
if self.company_id.country_id.code != 'UY':
raise UserError(_("Solo puede generar este reporte para compañias Uruguayas"))

data = getattr(self, '_get_form_%s_data' % self.uy_form_id)()
data = getattr(self, '_get_form_%s_data' % self.uy_form_id)() if self.uy_form_id else None
if data:
self.res_filename = self.company_id.name[:4] + "Formulario2-181DGI_" + self.date_period[-2:] + self.date_period[:4] + ".txt"
# TODO No sabemos realmente cual es el formato, solo tomamos de ejemplo el que genera uruware
Expand Down

0 comments on commit 5a99a74

Please sign in to comment.