diff --git a/addons/account/models/__init__.py b/addons/account/models/__init__.py index d9e2695b020..0322c41fd1d 100644 --- a/addons/account/models/__init__.py +++ b/addons/account/models/__init__.py @@ -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 diff --git a/addons/account/models/account_tax_carryover_line.py b/addons/account/models/account_tax_carryover_line.py new file mode 100644 index 00000000000..ee9a7065288 --- /dev/null +++ b/addons/account/models/account_tax_carryover_line.py @@ -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.")) diff --git a/addons/account/models/account_tax_report.py b/addons/account/models/account_tax_report.py index 2533002972a..e7b34becc05 100644 --- a/addons/account/models/account_tax_report.py +++ b/addons/account/models/account_tax_report.py @@ -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) diff --git a/addons/account/security/account_security.xml b/addons/account/security/account_security.xml index 6fc42d68ea8..5fe852d5d07 100644 --- a/addons/account/security/account_security.xml +++ b/addons/account/security/account_security.xml @@ -275,5 +275,10 @@ ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + Carry over line multi-company + + [('company_id', 'in', company_ids)] + diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv index cddbb5372f2..b6a47288b84 100644 --- a/addons/account/security/ir.model.access.csv +++ b/addons/account/security/ir.model.access.csv @@ -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 \ No newline at end of file +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 diff --git a/addons/account/views/account_tax_report_views.xml b/addons/account/views/account_tax_report_views.xml index 26737629c9a..9e31fb76e81 100644 --- a/addons/account/views/account_tax_report_views.xml +++ b/addons/account/views/account_tax_report_views.xml @@ -49,6 +49,21 @@ + + account.tax.carryover.line.tree + account.tax.carryover.line + + + + + + + + + + + + account.tax.report.line.form account.tax.report.line @@ -70,9 +85,22 @@ - - + + + + + + + + + + + + + + + diff --git a/addons/l10n_be/data/account_tax_report_data.xml b/addons/l10n_be/data/account_tax_report_data.xml index 6b21b5c1124..d2664138fbb 100644 --- a/addons/l10n_be/data/account_tax_report_data.xml +++ b/addons/l10n_be/data/account_tax_report_data.xml @@ -160,6 +160,7 @@ 1 + no_negative_amount_carry_over_condition @@ -169,6 +170,7 @@ 2 + no_negative_amount_carry_over_condition @@ -178,6 +180,7 @@ 3 + no_negative_amount_carry_over_condition @@ -205,6 +208,7 @@ 6 + no_negative_amount_carry_over_condition @@ -214,6 +218,7 @@ 7 + no_negative_amount_carry_over_condition @@ -223,6 +228,7 @@ 8 + no_negative_amount_carry_over_condition