Skip to content

Commit

Permalink
[11.0][ADD] l10n_nl_tax_statement_icp
Browse files Browse the repository at this point in the history
  • Loading branch information
astirpe committed Sep 10, 2018
1 parent 2d82745 commit 58b0ba3
Show file tree
Hide file tree
Showing 18 changed files with 574 additions and 0 deletions.
89 changes: 89 additions & 0 deletions l10n_nl_tax_statement_icp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3

=========================
Netherlands ICP Statement
=========================

This module extends the *Netherlands BTW Statement* module (BTW aangifte report), by adding the statement for the *Intra-Community transactions declaration* (ICP declaration).

The ICP declaration report is based on line *3b - Leveringen naar landen binnen de EU (omzet)* of the BTW aangifte report.
The period is also the same as the one selected in the BTW aangifte report.

This ICP declaration report includes:

* the VAT identification numbers of your customers;
* the total amount of intra-Community supplies from the Netherlands for every customer during the selected period.

Installation
============

To install this module, you need to:

#. Install module *l10n_nl_tax_statement* version >= *11.0.2.0.0*.

Configuration
=============

To configure this module, you need to:

#. Follow the configuration steps as described in *l10n_nl_tax_statement* and set the tag *3b omzet* needed for this report.

Usage
=====

To use this module, you need to:

#. Create a BTW Statement.
#. Post the BTW Statement: a new tab *ICP Statement* will be displayed; the tab contains the lines of the ICP declaration report.
#. In tab *ICP Statement* press the Update button in order to recompute the ICP statement lines.

Printing a PDF report:

#. If you need to print the report in PDF, open a statement form and click: `Print -> NL ICP Statement`


.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/176/11.0


Known issues / Roadmap
======================

* Add checks to avoid errors in the report, e.g. no country, wrong country, no VAT code, tax-code not matching fiscal position, etc..
* Add unit tests

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/OCA/l10n-netherlands/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.

Credits
=======

Contributors
------------

* Andrea Stirpe <a.stirpe@onestein.nl>

Do not contact contributors directly about support or help with technical issues.

Maintainer
----------

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

This module is maintained by the OCA.

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

To contribute to this module, please visit https://odoo-community.org.
1 change: 1 addition & 0 deletions l10n_nl_tax_statement_icp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
21 changes: 21 additions & 0 deletions l10n_nl_tax_statement_icp/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2018 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
'name': 'Netherlands ICP Statement',
'version': '11.0.1.0.0',
'category': 'Localization',
'license': 'AGPL-3',
'author': 'Onestein, Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/l10n-netherlands',
'depends': [
'l10n_nl_tax_statement',
],
'data': [
'security/ir.model.access.csv',
'views/l10n_nl_vat_statement_view.xml',
'views/report_tax_statement.xml',
'report/report_tax_statement.xml',
],
'installable': True,
}
2 changes: 2 additions & 0 deletions l10n_nl_tax_statement_icp/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import l10n_nl_vat_statement
from . import l10n_nl_vat_statement_icp_line
201 changes: 201 additions & 0 deletions l10n_nl_tax_statement_icp/models/l10n_nl_vat_statement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Copyright 2018 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import api, fields, models, _
from odoo.exceptions import UserError


class VatStatement(models.Model):
_inherit = 'l10n.nl.vat.statement'

tag_3b_omzet = fields.Many2one(
'account.account.tag',
compute='_compute_tag_3b_omzet'
)
tag_3b_omzet_d = fields.Many2one(
'account.account.tag',
compute='_compute_tag_3b_omzet'
)
icp_line_ids = fields.One2many(
'l10n.nl.vat.statement.icp.line',
'statement_id',
string='ICP Lines',
readonly=True
)
icp_total = fields.Monetary(
string='Total ICP amount',
readonly=True,
help='Total amount in currency of the statement.'
)

@api.depends('company_id')
def _compute_tag_3b_omzet(self):
''' Computes Tag 3b omzet'''
for statement in self:
config = self.env['l10n.nl.vat.statement.config'].search([
('company_id', '=', statement.company_id.id)
], limit=1)
statement.tag_3b_omzet = config.tag_3b_omzet
statement.tag_3b_omzet_d = config.tag_3b_omzet_d

@api.multi
def _compute_icp_lines(self):
''' Computes ICP lines for the report'''
IcpLine = self.env['l10n.nl.vat.statement.icp.line']
for statement in self:
statement.icp_line_ids.unlink()
statement.icp_total = 0.0
amounts_map = statement._get_partner_amounts_map()
for partner_id in amounts_map:
icp_values = self._prepare_icp_line(amounts_map[partner_id])
icp_values['partner_id'] = partner_id
icp_values['statement_id'] = statement.id
newline = IcpLine.create(icp_values)
statement.icp_line_ids += newline
icp_total = newline.amount_products + newline.amount_services
statement.icp_total += icp_total

@api.model
def _prepare_icp_line(self, partner_amounts):
''' Prepares an internal data structure representing the ICP line'''
return {
'country_code': partner_amounts['country_code'],
'vat': partner_amounts['vat'],
'amount_products': partner_amounts['amount_products'],
'amount_services': partner_amounts['amount_services'],
'currency_id': partner_amounts['currency_id'],
}

@api.multi
def _is_3b_omzet_line(self, line):
self.ensure_one()

tag_3b_omzet = self.tag_3b_omzet
for tax in line.tax_ids:
if tax.tag_ids.filtered(
lambda r: r == tag_3b_omzet):
return True
return False

@api.multi
def _is_3b_omzet_diensten_line(self, line):
self.ensure_one()

tag_3b_omzet_d = self.tag_3b_omzet_d
for tax in line.tax_ids:
if tax.tag_ids.filtered(
lambda r: r == tag_3b_omzet_d):
return True
return False

@api.multi
def _get_partner_amounts_map(self):
''' Generate an internal data structure representing the ICP line'''
self.ensure_one()

partner_amounts_map = {}
for line in self.move_line_ids:
is_3b_omzet = self._is_3b_omzet_line(line)
is_3b_omzet_diensten = self._is_3b_omzet_diensten_line(line)
if is_3b_omzet or is_3b_omzet_diensten:
vals = self._prepare_icp_line_from_move_line(line)
if vals['partner_id'] not in partner_amounts_map:
self._init_partner_amounts_map(partner_amounts_map, vals)
self._update_partner_amounts_map(partner_amounts_map, vals)
return partner_amounts_map

@api.multi
def _check_config_tag_3b_omzet(self):
''' Checks the tag 3b Omzet, as configured for the BTW statement'''
if self._context.get('skip_check_config_tag_3b_omzet'):
return
for statement in self:
if not statement.tag_3b_omzet or not statement.tag_3b_omzet_d:
raise UserError(
_('Tag 3b omzet not configured for this Company! '
'Check the NL BTW Tags Configuration.'))

@classmethod
def _update_partner_amounts_map(cls, partner_amounts_map, vals):
''' Update amounts of the internal ICP lines data structure'''
map_data = partner_amounts_map[vals['partner_id']]
map_data['amount_products'] += vals['amount_products']
map_data['amount_services'] += vals['amount_services']

@classmethod
def _init_partner_amounts_map(cls, partner_amounts_map, vals):
''' Initialize the internal ICP lines data structure'''
partner_amounts_map[vals['partner_id']] = {
'country_code': vals['country_code'],
'vat': vals['vat'],
'currency_id': vals['currency_id'],
'amount_products': 0.0,
'amount_services': 0.0,
}

@api.multi
def _prepare_icp_line_from_move_line(self, line):
''' Gets move line details and prepares ICP report line data'''
self.ensure_one()

balance = line.balance
if line.currency_id and line.currency_id != self.currency_id:
balance = line.currency_id.with_context(
date=line.date
).compute(balance, self.currency_id, round=True)
amount_products = balance
amount_services = 0.0
if self._is_3b_omzet_diensten_line(line):
amount_products = 0.0
amount_services = balance

return {
'partner_id': line.partner_id.id,
'country_code': line.partner_id.country_id.code,
'vat': line.partner_id.vat,
'amount_products': amount_products,
'amount_services': amount_services,
'currency_id': self.currency_id.id,
}

@api.multi
def reset(self):
''' Removes ICP lines if reset to draft'''
for statement in self:
statement.icp_line_ids.unlink()
return super(VatStatement, self).reset()

@api.multi
def post(self):
''' Checks configuration when validating the statement'''
self.ensure_one()
self._check_config_tag_3b_omzet()
res = super(VatStatement, self).post()
self._compute_icp_lines()
return res

@api.model
def _modifiable_values_when_posted(self):
''' Returns the modifiable fields even when the statement is posted'''
res = super(VatStatement, self)._modifiable_values_when_posted()
res.append('icp_line_ids')
res.append('icp_total')
return res

@api.multi
def icp_update(self):
''' Update button'''
self.ensure_one()

if self.state in ['final']:
raise UserError(
_('You cannot modify a final statement!'))

# clean old lines
self.icp_line_ids.unlink()

# check config
self._check_config_tag_3b_omzet()

# create lines
self._compute_icp_lines()
49 changes: 49 additions & 0 deletions l10n_nl_tax_statement_icp/models/l10n_nl_vat_statement_icp_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2018 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import api, fields, models
from odoo.tools.misc import formatLang


class VatStatementIcpLine(models.Model):
_name = 'l10n.nl.vat.statement.icp.line'
_description = 'Intra-Community transactions (ICP) line'
_order = 'partner_id, country_code'

statement_id = fields.Many2one(
'l10n.nl.vat.statement',
'Statement',
ondelete='cascade'
)
partner_id = fields.Many2one(
'res.partner',
string='Partner',
readonly=True,
required=True,
)
vat = fields.Char(
string='VAT',
readonly=True,
)
country_code = fields.Char(
readonly=True,
)
currency_id = fields.Many2one(
'res.currency',
string='Currency',
readonly=True
)
amount_products = fields.Monetary(readonly=True)
format_amount_products = fields.Char(compute='_compute_icp_amount_format')
amount_services = fields.Monetary(readonly=True)
format_amount_services = fields.Char(compute='_compute_icp_amount_format')

@api.depends('amount_products', 'amount_services')
def _compute_icp_amount_format(self):
for line in self:
amount_products = formatLang(
self.env, line.amount_products, monetary=True)
amount_services = formatLang(
self.env, line.amount_services, monetary=True)
line.format_amount_products = amount_products
line.format_amount_services = amount_services
3 changes: 3 additions & 0 deletions l10n_nl_tax_statement_icp/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
To configure this module, you need to:

#. Follow the configuration steps as described in *l10n_nl_tax_statement* and set the tag *3b omzet* needed for this report.
1 change: 1 addition & 0 deletions l10n_nl_tax_statement_icp/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Andrea Stirpe <a.stirpe@onestein.nl>
9 changes: 9 additions & 0 deletions l10n_nl_tax_statement_icp/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This module extends the *Netherlands BTW Statement* module (BTW aangifte report), by adding the statement for the *Intra-Community transactions declaration* (ICP declaration).

The ICP declaration report is based on line *3b - Leveringen naar landen binnen de EU (omzet)* of the BTW aangifte report.
The period is also the same as the one selected in the BTW aangifte report.

This ICP declaration report includes:

* the VAT identification numbers of your customers;
* the total amount of intra-Community supplies from the Netherlands for every customer during the selected period.
3 changes: 3 additions & 0 deletions l10n_nl_tax_statement_icp/readme/INSTALL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
To install this module, you need to:

#. Install module *l10n_nl_tax_statement* version >= *11.0.2.0.0*.
2 changes: 2 additions & 0 deletions l10n_nl_tax_statement_icp/readme/ROADMAP.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Add checks to avoid errors in the report, e.g. no country, wrong country, no VAT code, tax-code not matching fiscal position, etc..
* Add unit tests
Loading

0 comments on commit 58b0ba3

Please sign in to comment.