[IMP] account_reports: allow to carry over lines between periods
In belgian accounting, some tax lines in the tax report must be carried over to the next period if they are negative. If the balance for the next period is positive, it will be deduced by the maximum possible amount that is carried over. If it is negative, the negative balance will simply be added to the carried over balance. This process repeats itself from one period to the other endlessly, until the carried over balance come back to 0. This is done by putting the carried over balance in dedicated analytic accounts. task id #2271978
This commit is contained in:
@@ -7,6 +7,7 @@ from . import account_account_tag
|
||||
from . import account_account
|
||||
from . import account_journal
|
||||
from . import account_tax
|
||||
from . import account_tax_carryover_line
|
||||
from . import account_tax_report
|
||||
from . import account_reconcile_model
|
||||
from . import account_payment_term
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
class AccountTaxCarryoverLine(models.Model):
|
||||
_name = 'account.tax.carryover.line'
|
||||
_description = 'Tax carryover line'
|
||||
|
||||
name = fields.Char(required=True)
|
||||
amount = fields.Float(required=True, default=0.0)
|
||||
date = fields.Date(required=True, default=fields.Date.context_today, readonly=True)
|
||||
tax_report_line_id = fields.Many2one(comodel_name='account.tax.report.line', string="Tax report line")
|
||||
tax_report_country_id = fields.Many2one(related='tax_report_line_id.report_id.country_id')
|
||||
company_id = fields.Many2one(comodel_name='res.company', string='Company',
|
||||
required=True,
|
||||
default=lambda self: self.env.company)
|
||||
foreign_vat_fiscal_position_id = fields.Many2one(comodel_name='account.fiscal.position',
|
||||
string='Fiscal position',
|
||||
help="The foreign fiscal position for which this carryover is made.",
|
||||
domain=[('company_id', '=', company_id),
|
||||
('country_id', '=', tax_report_country_id),
|
||||
('foreign_vat', '!=', False)])
|
||||
|
||||
@api.constrains('foreign_vat_fiscal_position_id')
|
||||
def _check_fiscal_position(self):
|
||||
if self.foreign_vat_fiscal_position_id and not self.foreign_vat_fiscal_position_id.country_id == self.tax_report_country_id:
|
||||
raise ValidationError(_("The country of the fiscal position must be this report line's report country."))
|
||||
@@ -75,11 +75,12 @@ class AccountTaxReport(models.Model):
|
||||
lines_to_treat = list(to_yield.children_line_ids.sorted(lambda x: x.sequence)) + lines_to_treat[1:]
|
||||
yield to_yield
|
||||
|
||||
def get_checks_to_perform(self, d):
|
||||
def get_checks_to_perform(self, amounts, carried_over):
|
||||
""" To override in localizations
|
||||
If value is a float, it will be formatted with format_value
|
||||
The line is not displayed if it is falsy (0, 0.0, False, ...)
|
||||
:param d: the mapping dictionay between codes and values
|
||||
:param amounts: the mapping dictionary between codes and values
|
||||
:param carried_over: the mapping dictionary between codes and whether they are carried over
|
||||
:return: iterable of tuple (name, value)
|
||||
"""
|
||||
self.ensure_one()
|
||||
@@ -107,13 +108,34 @@ class AccountTaxReportLine(models.Model):
|
||||
parent_path = fields.Char(index=True)
|
||||
report_id = fields.Many2one(string="Tax Report", required=True, comodel_name='account.tax.report', ondelete='cascade', help="The parent tax report of this line")
|
||||
|
||||
#helper to create tags (positive and negative) on report line creation
|
||||
# helper to create tags (positive and negative) on report line creation
|
||||
tag_name = fields.Char(string="Tag Name", help="Short name for the tax grid corresponding to this report line. Leave empty if this report line should not correspond to any such grid.")
|
||||
|
||||
#fields used in specific localization reports, where a report line isn't simply the given by the sum of account.move.line with selected tags
|
||||
# fields used in specific localization reports, where a report line isn't simply the given by the sum of account.move.line with selected tags
|
||||
code = fields.Char(string="Code", help="Optional unique code to refer to this line in total formulas")
|
||||
formula = fields.Char(string="Formula", help="Python expression used to compute the value of a total line. This field is mutually exclusive with tag_name, setting it turns the line to a total line. Tax report line codes can be used as variables in this expression to refer to the balance of the corresponding lines in the report. A formula cannot refer to another line using a formula.")
|
||||
|
||||
# fields used to carry over amounts between periods
|
||||
|
||||
# The selection should be filled in localizations using the system
|
||||
carry_over_condition_method = fields.Selection(
|
||||
selection=[('no_negative_amount_carry_over_condition', 'No negative amount')],
|
||||
string="Carry over method",
|
||||
help="The method used to determine if this line should be carried over."
|
||||
)
|
||||
carry_over_destination_line_id = fields.Many2one(
|
||||
string="Carry over to",
|
||||
comodel_name="account.tax.report.line",
|
||||
domain=[('tag_name', '!=', False)],
|
||||
help="The line to which the value of this line will be carried over to if needed."
|
||||
" If left empty the line will carry over to itself."
|
||||
)
|
||||
carryover_line_ids = fields.One2many(
|
||||
string="Carryover lines",
|
||||
comodel_name='account.tax.carryover.line',
|
||||
inverse_name='tax_report_line_id',
|
||||
)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# Manage tags
|
||||
@@ -264,3 +286,32 @@ class AccountTaxReportLine(models.Model):
|
||||
|
||||
if neg_tags.name != '-'+record.tag_name or pos_tags.name != '+'+record.tag_name:
|
||||
raise ValidationError(_("The tags linked to a tax report line should always match its tag name."))
|
||||
|
||||
def _get_carryover_bounds(self, options, line_amount, carried_over_amount):
|
||||
"""
|
||||
Check if the line will be carried over, by checking the condition method set on the line.
|
||||
Do not override this method, but instead set your condition methods on each lines.
|
||||
:param options: The options of the reports
|
||||
:param line_amount: The amount on the line
|
||||
:param carried_over_amount: The amount carried over for this line
|
||||
:return: A tuple containing the lower and upper bounds from which the line will be carried over.
|
||||
E.g. (0, 42) : Lines which value is below 0 or above 42 will be carried over.
|
||||
E.g. (0, None) : Only lines which value is below 0 will be carried over.
|
||||
E.g. None : This line will never be carried over.
|
||||
"""
|
||||
self.ensure_one()
|
||||
# Carry over is disabled by default, but if there is a carry over condition method on the line we are
|
||||
# calling it first. That way we can have a default carryover condition for the whole report (carryover_bounds)
|
||||
# and specialized condition for specific lines if needed
|
||||
if self.carry_over_condition_method:
|
||||
condition_method = getattr(self, self.carry_over_condition_method, False)
|
||||
if condition_method:
|
||||
return condition_method(options, line_amount, carried_over_amount)
|
||||
|
||||
return None
|
||||
|
||||
def no_negative_amount_carry_over_condition(self, options, line_amount, carried_over_amount):
|
||||
# The bounds are (0, None).
|
||||
# Lines below 0 will be set to 0 and reduce the balance of the carryover.
|
||||
# Lines above 0 will never be carried over
|
||||
return (0, None)
|
||||
|
||||
@@ -275,5 +275,10 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="account_tax_carryover_line_comp_rule" model="ir.rule">
|
||||
<field name="name">Carry over line multi-company</field>
|
||||
<field name="model_id" ref="model_account_tax_carryover_line"/>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -91,6 +91,8 @@ access_account_tax_repartition_line_invoice,account.tax repartition.line.invoice
|
||||
access_account_tax_repartition_line_manager,account.tax repartition.line.manager,model_account_tax_repartition_line,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_report_line_readonly,account.tax.report.line.invoice,model_account_tax_report_line,account.group_account_readonly,1,0,0,0
|
||||
access_account_tax_report_line_ac_user,account.tax.report.line.ac.user,model_account_tax_report_line,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_carryover_line_readonly,account.tax.carryover.line.invoice,model_account_tax_carryover_line,account.group_account_readonly,1,0,0,0
|
||||
access_account_tax_carryover_line_ac_user,account.tax.carryover.line.ac.user,model_account_tax_carryover_line,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_report_invoice,account.tax.report.invoice,model_account_tax_report,account.group_account_readonly,1,0,0,0
|
||||
access_account_tax_report_ac_user,account.tax.report.ac.user,model_account_tax_report,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_group_internal_user,account.tax.group internal user,model_account_tax_group,base.group_user,1,0,0,0
|
||||
@@ -143,4 +145,4 @@ access_account_analytic_default,account.analytic.default,model_account_analytic_
|
||||
access_account_analytic_default_analytic,account.analytic.default analytic,model_account_analytic_default,analytic.group_analytic_accounting,1,0,0,0
|
||||
access_account_analytic_default_invoice,account.analytic.default invoice,model_account_analytic_default,account.group_account_invoice,1,1,1,1
|
||||
access_account_tour_upload_bill,account.tour.upload.bill,model_account_tour_upload_bill,account.group_account_manager,1,1,1,0
|
||||
access_account_tour_upload_bill_email_confirm,account.tour.upload.bill.email.confirm,model_account_tour_upload_bill_email_confirm,account.group_account_manager,1,1,1,0
|
||||
access_account_tour_upload_bill_email_confirm,account.tour.upload.bill.email.confirm,model_account_tour_upload_bill_email_confirm,account.group_account_manager,1,1,1,0
|
||||
|
||||
|
@@ -49,6 +49,21 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_tax_carryover_line_tree" model="ir.ui.view">
|
||||
<field name="name">account.tax.carryover.line.tree</field>
|
||||
<field name="model">account.tax.carryover.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="tax_report_country_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="date"/>
|
||||
<field name="amount"/>
|
||||
<field name="foreign_vat_fiscal_position_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_tax_report_line_form" model="ir.ui.view">
|
||||
<field name="name">account.tax.report.line.form</field>
|
||||
<field name="model">account.tax.report.line</field>
|
||||
@@ -70,9 +85,22 @@
|
||||
<group>
|
||||
<field name="formula"/>
|
||||
</group>
|
||||
<group string="Sublines">
|
||||
<field name="children_line_ids" context="{'default_report_id': report_id}"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="carry_over_condition_method"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="carry_over_destination_line_id" placeholder="Same report line"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Sublines">
|
||||
<field name="children_line_ids" context="{'default_report_id': report_id}"/>
|
||||
</page>
|
||||
<page string="Carry over lines">
|
||||
<field name="carryover_line_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">1</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_line_82" model="account.tax.report.line">
|
||||
@@ -169,6 +170,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_line_83" model="account.tax.report.line">
|
||||
@@ -178,6 +180,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">3</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_line_84" model="account.tax.report.line">
|
||||
@@ -205,6 +208,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_line_87" model="account.tax.report.line">
|
||||
@@ -214,6 +218,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">7</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_line_88" model="account.tax.report.line">
|
||||
@@ -223,6 +228,7 @@
|
||||
<field name="report_id" ref="tax_report_vat"/>
|
||||
<field name="parent_id" ref="tax_report_title_operations_entree"/>
|
||||
<field name="sequence">8</field>
|
||||
<field name="carry_over_condition_method">no_negative_amount_carry_over_condition</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_report_title_taxes" model="account.tax.report.line">
|
||||
|
||||
Reference in New Issue
Block a user