10 changed files with 318 additions and 0 deletions
-
73partner_contact_vat/README.rst
-
5partner_contact_vat/__init__.py
-
23partner_contact_vat/__openerp__.py
-
42partner_contact_vat/i18n/es.po
-
5partner_contact_vat/models/__init__.py
-
51partner_contact_vat/models/res_partner.py
-
BINpartner_contact_vat/static/description/icon.png
-
5partner_contact_vat/tests/__init__.py
-
54partner_contact_vat/tests/test_validation.py
-
60partner_contact_vat/view/res_partner.xml
@ -0,0 +1,73 @@ |
|||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
======================= |
||||
|
VAT in contact partners |
||||
|
======================= |
||||
|
|
||||
|
This module was written to extend the functionality of contacts management to |
||||
|
support setting a VAT in contact partners (those partners that are not not |
||||
|
companies) and allow you to have separate VAT codes for contact and for their |
||||
|
company. |
||||
|
|
||||
|
Odoo by default only allows VAT in companies. When a contact belongs to a |
||||
|
company and you go to *accounting* page, it shows *Accounting is managed in the |
||||
|
parent company*. |
||||
|
|
||||
|
If you manage any kind of personal information of your clients (prevention of |
||||
|
occupational hazards, training, event assistants, legal stuff, etc.) you |
||||
|
probably need their VAT. |
||||
|
|
||||
|
Indeed the company VAT will still be used for invoices and other legal |
||||
|
documents, but for other things you need the person's. For that reason, instead |
||||
|
of overwriting the VAT field, this module just adds a new one that will be |
||||
|
hidden for companies. |
||||
|
|
||||
|
You will not be able to save a contact VAT with an invalid format. |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
To use this module, you need to: |
||||
|
|
||||
|
* Go to any contact's form. |
||||
|
* Enter its *personal information* page. |
||||
|
|
||||
|
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
||||
|
:alt: Try me on Runbot |
||||
|
:target: https://runbot.odoo-community.org/runbot/134/8.0 |
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/ |
||||
|
partner-contact/issues>`_. In case of trouble, please check there if your issue |
||||
|
has already been reported. If you spotted it first, help us smashing it by |
||||
|
providing a detailed and welcomed feedback `here <https://github.com/OCA/ |
||||
|
partner-contact/issues/new?body=module:%20 |
||||
|
partner_contact_vat%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
||||
|
|
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Jairo Llopis <j.llopis@grupoesoc.es> |
||||
|
|
||||
|
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. |
@ -0,0 +1,5 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import models |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
{ |
||||
|
"name": "VAT in contact partners", |
||||
|
"summary": "Allow to set up VAT for contacts", |
||||
|
"version": "8.0.1.0.0", |
||||
|
"category": "Accounting & Finance", |
||||
|
"website": "https://grupoesoc.es", |
||||
|
"author": "Grupo ESOC Ingeniería de servicios, " |
||||
|
"Odoo Community Association (OCA)", |
||||
|
"license": "AGPL-3", |
||||
|
"application": False, |
||||
|
"installable": True, |
||||
|
"depends": [ |
||||
|
"base_vat", |
||||
|
"partner_contact_personal_information_page", |
||||
|
], |
||||
|
"data": [ |
||||
|
"view/res_partner.xml", |
||||
|
], |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * partner_contact_vat |
||||
|
# |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 7.0-20140804-231303\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2014-08-08 09:55+0000\n" |
||||
|
"PO-Revision-Date: 2014-08-08 11:58+0100\n" |
||||
|
"Last-Translator: Jairo Llopis <yajo.sk8@gmail.com>\n" |
||||
|
"Language-Team: \n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: 8bit\n" |
||||
|
"X-Generator: Poedit 1.5.4\n" |
||||
|
"Language: es\n" |
||||
|
|
||||
|
#. module: partner_contact_vat |
||||
|
#: model:ir.model,name:partner_contact_vat.model_res_partner |
||||
|
msgid "Partner" |
||||
|
msgstr "Empresa" |
||||
|
|
||||
|
#. module: partner_contact_vat |
||||
|
#: help:res.partner,contact_vat:0 |
||||
|
msgid "" |
||||
|
"Tax Identification Number of the contact. This will not be used for " |
||||
|
"commercial actions; instead, parent company's TIN will be used." |
||||
|
msgstr "" |
||||
|
"Número de Identificación Fiscal del contacto. Este código no se usará para " |
||||
|
"acciones comerciales; en su lugar, se usará el NIF de la empresa a la que " |
||||
|
"pertenece el contacto." |
||||
|
|
||||
|
#. module: partner_contact_vat |
||||
|
#: field:res.partner,contact_vat:0 |
||||
|
msgid "Contact TIN" |
||||
|
msgstr "NIF del contacto" |
||||
|
|
||||
|
#. module: partner_contact_vat |
||||
|
#: view:res.partner:0 |
||||
|
msgid "e.g. BE0477472701" |
||||
|
msgstr "Por ejemplo, ESA00000000" |
@ -0,0 +1,5 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import res_partner |
@ -0,0 +1,51 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import string |
||||
|
from openerp import _, api, exceptions, fields, models |
||||
|
from openerp.addons.base_vat.base_vat import _ref_vat |
||||
|
|
||||
|
|
||||
|
class PartnerVATInContacts(models.Model): |
||||
|
"""Allow to set up individual VAT for a company's contacts.""" |
||||
|
_inherit = "res.partner" |
||||
|
|
||||
|
contact_vat = fields.Char( |
||||
|
"Contact TIN", |
||||
|
size=32, |
||||
|
help="Tax Identification Number of the contact. " |
||||
|
"This will not be used for commercial actions; " |
||||
|
"instead, parent company's TIN will be used.") |
||||
|
|
||||
|
@api.multi |
||||
|
@api.constrains("is_company", "contact_vat") |
||||
|
def contact_vat_check(self): |
||||
|
"""Check validity of `contact_vat`. |
||||
|
|
||||
|
It does not use VIES because usually it would fail when checking |
||||
|
persons' VAT codes. |
||||
|
""" |
||||
|
for s in self.filtered(lambda r: not r.is_company and r.contact_vat): |
||||
|
country, code = s._split_vat(s.contact_vat) |
||||
|
values = { |
||||
|
"vat": s.contact_vat, |
||||
|
"name": s.display_name, |
||||
|
} |
||||
|
|
||||
|
# VAT should start with 2 letters |
||||
|
if any(char not in string.ascii_lowercase for char in country): |
||||
|
raise exceptions.ValidationError( |
||||
|
_("VAT %(vat)s of %(name)s should start with " |
||||
|
"2 letters that indicate the country code.") % values) |
||||
|
|
||||
|
# Use core methods for VAT checking |
||||
|
elif not s.simple_vat_check(country, code): |
||||
|
# Display a useful message to user |
||||
|
values["template"] = ( |
||||
|
_ref_vat.get(country) or |
||||
|
_("CCNNNNNNNNN (CC=Country Code of 2 letters, " |
||||
|
"NNN... Local VAT number).")) |
||||
|
raise exceptions.ValidationError( |
||||
|
_("VAT %(vat)s of %(name)s has a wrong format. " |
||||
|
"It should be similar to %(template)s") % values) |
After Width: 100 | Height: 100 | Size: 18 KiB |
@ -0,0 +1,5 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import test_validation |
@ -0,0 +1,54 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp.tests.common import TransactionCase |
||||
|
from openerp.addons.base_vat.base_vat import _ref_vat |
||||
|
from openerp import exceptions as ex |
||||
|
|
||||
|
|
||||
|
class CommonCase(TransactionCase): |
||||
|
"""Test common cases, independent to the country of the VAT code.""" |
||||
|
def setUp(self): |
||||
|
super(CommonCase, self).setUp() |
||||
|
|
||||
|
self.partner = self.env["res.partner"].create({ |
||||
|
"name": __file__, |
||||
|
"is_company": False, |
||||
|
}) |
||||
|
|
||||
|
def test_empty(self): |
||||
|
"""Remove a VAT from a contact.""" |
||||
|
# First, set a good VAT to have no errors |
||||
|
self.partner.contact_vat = "ES00000001R" |
||||
|
|
||||
|
# Then remove it |
||||
|
self.partner.contact_vat = False |
||||
|
|
||||
|
# Nothing special should happen |
||||
|
self.assertEqual(self.partner.contact_vat, False) |
||||
|
|
||||
|
def test_company_to_partner(self): |
||||
|
"""Set a wrong contact VAT to a company and convert it to person.""" |
||||
|
self.partner.is_company = True |
||||
|
|
||||
|
# Set a wrong contact_vat, but no errors because it is a company |
||||
|
self.partner.contact_vat = "ES00000001W" |
||||
|
|
||||
|
# Now say it's a person |
||||
|
with self.assertRaises(ex.ValidationError): |
||||
|
self.partner.is_company = False |
||||
|
|
||||
|
def test_vat_without_country_code(self): |
||||
|
"""Set a VAT without the country code prefix.""" |
||||
|
with self.assertRaises(ex.ValidationError): |
||||
|
self.partner.contact_vat = "00000001R" |
||||
|
|
||||
|
def test_wrong_format_hint(self): |
||||
|
"""Ensure the format hint is given to user.""" |
||||
|
try: |
||||
|
# Set a wrong VAT |
||||
|
self.partner.with_context(lang="en_US").contact_vat = "ES00000001W" |
||||
|
except ex.ValidationError as error: |
||||
|
self.assertIn(_ref_vat.get("es"), error.value) |
||||
|
self.assertEqual(error.value, error.args[1]) |
@ -0,0 +1,60 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
|
||||
|
<!-- © 2015 Grupo ESOC Ingeniería de servicios, S.L. - Jairo Llopis |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
||||
|
|
||||
|
<openerp> |
||||
|
<data> |
||||
|
|
||||
|
<record id="partner_form" model="ir.ui.view"> |
||||
|
<field name="name">VAT for contacts</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="inherit_id" ref="partner_contact_personal_information_page.personal_information"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<data> |
||||
|
<!-- Accounting page --> |
||||
|
<xpath expr="//group[@name='personal_information_group']"> |
||||
|
<group> |
||||
|
<label for="contact_vat"/> |
||||
|
<div name="contact_vat_main"> |
||||
|
<field |
||||
|
name="contact_vat" |
||||
|
placeholder="e.g. BE0477472701" |
||||
|
class="oe_inline"/> |
||||
|
<button |
||||
|
colspan="2" |
||||
|
name="contact_vat_check" |
||||
|
string="Check Validity" |
||||
|
type="object" |
||||
|
icon="gtk-execute" |
||||
|
class="oe_inline"/> |
||||
|
</div> |
||||
|
</group> |
||||
|
</xpath> |
||||
|
|
||||
|
<!-- Contacts subform --> |
||||
|
<xpath expr="//page[@string='Contacts'] |
||||
|
//form[@string='Contact'] |
||||
|
//field[@name='mobile']" |
||||
|
position="after"> |
||||
|
<label for="contact_vat"/> |
||||
|
<div name="contact_vat_subform"> |
||||
|
<field |
||||
|
name="contact_vat" |
||||
|
placeholder="e.g. BE0477472701" |
||||
|
class="oe_inline"/> |
||||
|
<button |
||||
|
colspan="2" |
||||
|
name="contact_vat_check" |
||||
|
string="Check Validity" |
||||
|
type="object" |
||||
|
icon="gtk-execute" |
||||
|
class="oe_inline"/> |
||||
|
</div> |
||||
|
</xpath> |
||||
|
</data> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue