Browse Source

Merge PR #1152 into 14.0

Signed-off-by rafaelbn
14.0
OCA-git-bot 2 years ago
parent
commit
27a6852e47
  1. 1
      partner_data_vies_populator/README.rst
  2. 1
      partner_data_vies_populator/__init__.py
  3. 19
      partner_data_vies_populator/__manifest__.py
  4. 19
      partner_data_vies_populator/i18n/partner_data_vies_populator.pot
  5. 1
      partner_data_vies_populator/models/__init__.py
  6. 64
      partner_data_vies_populator/models/res_partner.py
  7. 9
      partner_data_vies_populator/readme/CONTRIBUTORS.rst
  8. 7
      partner_data_vies_populator/readme/DESCRIPTION.rst
  9. 1
      partner_data_vies_populator/readme/INSTALL.rst
  10. 1
      partner_data_vies_populator/readme/USAGE.rst
  11. BIN
      partner_data_vies_populator/static/description/icon.png
  12. 443
      partner_data_vies_populator/static/description/index.html
  13. 1
      partner_data_vies_populator/tests/__init__.py
  14. 85
      partner_data_vies_populator/tests/test_partner_data_vies_populator.py
  15. 1
      requirements.txt
  16. 1
      setup/partner_data_vies_populator/odoo/addons/partner_data_vies_populator
  17. 6
      setup/partner_data_vies_populator/setup.py

1
partner_data_vies_populator/README.rst

@ -0,0 +1 @@
Will be regenerated from readme subdir

1
partner_data_vies_populator/__init__.py

@ -0,0 +1 @@
from . import models

19
partner_data_vies_populator/__manifest__.py

@ -0,0 +1,19 @@
# Copyright (C) 2015 Forest and Biomass Romania
# Copyright (C) 2020 NextERP Romania
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Partner Data VIES Populator",
"summary": "Using VIES webservice, name and address information will "
"be fetched and added to the partner.",
"version": "14.0.1.0.0",
"category": "Customer Relationship Management",
"author": "NextERP Romania,"
"Forest and Biomass Romania,"
"Odoo Community Association (OCA)",
"website": "https://github.com/OCA/partner-contact",
"license": "AGPL-3",
"depends": ["base_vat"],
"external_dependencies": {"python": ["python-stdnum"]},
"installable": True,
}

19
partner_data_vies_populator/i18n/partner_data_vies_populator.pot

@ -0,0 +1,19 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_data_vies_populator
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: partner_data_vies_populator
#: model:ir.model,name:partner_data_vies_populator.model_res_partner
msgid "Contact"
msgstr ""

1
partner_data_vies_populator/models/__init__.py

@ -0,0 +1 @@
from . import res_partner

64
partner_data_vies_populator/models/res_partner.py

@ -0,0 +1,64 @@
# Copyright (C) 2015 Forest and Biomass Romania
# Copyright (C) 2020 NextERP Romania
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import logging
from odoo import _, api, models
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
try:
from stdnum.eu.vat import check_vies
except ImportError:
_logger.debug("Cannot import check_vies method from python stdnum.")
class ResPartner(models.Model):
_inherit = "res.partner"
@api.model
def _get_vies_data(self, vat, raise_if_fail=False):
res = {}
try:
result = check_vies(vat)
except Exception as e:
_logger.warning("Failed to query VIES: %s" % e)
if raise_if_fail:
raise UserError(_("Failed to query VIES.\nTechnical error: %s.") % e)
return res
if result.valid and result.name:
res["vat"] = vat
# Update partner name if listed on VIES
if result.name != "---":
res["name"] = result.name.upper()
# Update partner address if listed on VIES
if result.address != "---":
res["street"] = (
result.address.replace("\n", " ").replace("\r", "").title()
)
# Get country by country code
country = self.env["res.country"].search(
[("code", "ilike", result.countryCode)]
)
if country:
res["country_id"] = country[0].id
return res
@api.onchange("vat")
def vies_vat_change(self):
eu_group = self.env.ref("base.europe", raise_if_not_found=False)
if eu_group:
for partner in self:
if not partner.vat or not partner.is_company:
continue
vat = partner.vat.strip().upper()
vat_country, vat_number = self._split_vat(vat)
vat_country = vat_country.upper()
eu_countries = eu_group.country_ids.mapped("code")
if vat_country and vat_country not in eu_countries:
continue
result = self._get_vies_data(vat)
if result:
partner.update(result)

9
partner_data_vies_populator/readme/CONTRIBUTORS.rst

@ -0,0 +1,9 @@
* `NextERP Romania <https://www.nexterp.ro>`_:
* Fekete Mihai <feketemihai@nexterp.ro>
* `Forest and Biomass Romania <https://www.forbiom.eu/>`_
* `Akretion <https://akretion.com/>`_ :
* Alexis de Lattre <alexis.delattre@akretion.com>

7
partner_data_vies_populator/readme/DESCRIPTION.rst

@ -0,0 +1,7 @@
This module allows you to create the partners (companies) based on their VAT number.
Name and address of the partner will automatically be completed via VIES Webservice.
VIES Service (based on stdnum python)
http://ec.europa.eu/taxation_customs/vies/vieshome.do
Unfortunately, VIES doesn't return a structured address but just a one-line address that aggregate street, zip and city. So, when you use this module to create a partner, the *City* and *Zip* fields will be left empty ; the *Street* field will contain the one-line address.

1
partner_data_vies_populator/readme/INSTALL.rst

@ -0,0 +1 @@
This module require the `python-stdnum <https://pypi.org/project/python-stdnum/>`_ librairy. As Odoo itself depend on this librairy, it should already be installed on your system.

1
partner_data_vies_populator/readme/USAGE.rst

@ -0,0 +1 @@
When changing a company partner VAT number, this module will try to fetch the partner data from VIES webservice, if available on VIES will update the name, address and country.

BIN
partner_data_vies_populator/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

443
partner_data_vies_populator/static/description/index.html

@ -0,0 +1,443 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Partner Data VIES Populator</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="partner-data-vies-populator">
<h1 class="title">Partner Data VIES Populator</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/partner-contact/tree/13.0/partner_data_vies_populator"><img alt="OCA/partner-contact" src="https://img.shields.io/badge/github-OCA%2Fpartner--contact-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/partner-contact-13-0/partner-contact-13-0-partner_data_vies_populator"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/134/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module allows you to create the partners (companies) based on their VAT number.
Name and address of the partner will automatically be completed via VIES Webservice.</p>
<p>VIES Service (based on stdnum python)
<a class="reference external" href="http://ec.europa.eu/taxation_customs/vies/vieshome.do">http://ec.europa.eu/taxation_customs/vies/vieshome.do</a></p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id1">Installation</a></h1>
<p>To install this module, you need to:</p>
<ol class="arabic simple">
<li>Clone the branch 13.0 of the repository <a class="reference external" href="https://github.com/OCA/partner-contact">https://github.com/OCA/partner-contact</a></li>
<li>Add the path to this repository in your configuration (addons-path)</li>
<li>Update the module list</li>
<li>Search for “Partner Data VIES Populator” in your addons</li>
<li>install the module</li>
</ol>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
<p>When changing a company partner VAT number, this module will try to fetch the partner data from VIES webservice, if available on VIES will update the name, address and country.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/partner-contact/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/partner-contact/issues/new?body=module:%20partner_data_vies_populator%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
<ul class="simple">
<li>NextERP Romania</li>
<li>Forest and Biomass Romania</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.nexterp.ro">NextERP Romania</a>:<ul>
<li>Fekete Mihai &lt;<a class="reference external" href="mailto:feketemihai&#64;nexterp.ro">feketemihai&#64;nexterp.ro</a>&gt;</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/partner-contact/tree/13.0/partner_data_vies_populator">OCA/partner-contact</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

1
partner_data_vies_populator/tests/__init__.py

@ -0,0 +1 @@
from . import test_partner_data_vies_populator

85
partner_data_vies_populator/tests/test_partner_data_vies_populator.py

@ -0,0 +1,85 @@
# Copyright (C) 2015 Forest and Biomass Romania
# Copyright (C) 2020 NextERP Romania
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import Form, TransactionCase
class TestPartnerCreateByVAT(TransactionCase):
def setUp(self):
super().setUp()
self.partner_model = self.env["res.partner"]
self.be_country_id = self.env.ref("base.be").id
self.sample_1 = {
"name": "SA ODOO",
"address": "Chaussée De Namur 40 1367 Ramillies",
"country_code": "BE",
}
def test_create_from_vat1(self):
# Create an partner from VAT number field
with Form(self.partner_model) as partner_form:
partner_form.is_company = True
partner_form.vat = "be0477472701"
# Check if the datas fetch correspond with the datas from VIES.
self.assertEqual(partner_form.name, self.sample_1["name"])
self.assertEqual(partner_form.street, self.sample_1["address"])
self.assertEqual(
partner_form.country_id.code, self.sample_1["country_code"]
)
self.assertEqual(partner_form.vat, "BE0477472701")
def test_company_vat_change(self):
# Change partner VAT number field
partner = self.partner_model.create({"name": "1", "is_company": True})
with Form(partner) as partner_form:
# Check if the datas fetch correspond with the datas from VIES.
partner_form.vat = "be0477472701"
self.assertEqual(partner_form.name, self.sample_1["name"])
self.assertEqual(partner_form.street, self.sample_1["address"])
self.assertEqual(
partner_form.country_id.code, self.sample_1["country_code"]
)
self.assertEqual(partner_form.vat, "BE0477472701")
def test_empty_vat_change(self):
partner = self.partner_model.create(
{
"name": "2",
"is_company": True,
"country_id": self.be_country_id,
}
)
with Form(partner) as partner_form:
partner_form.vat = False
self.assertEqual(partner_form.name, partner.name)
self.assertEqual(partner_form.street, False)
self.assertEqual(partner_form.country_id.id, partner.country_id.id)
def test_individual_vat_change(self):
partner = self.partner_model.create(
{
"name": "3",
"is_company": False,
"country_id": self.be_country_id,
}
)
with Form(partner) as partner_form:
partner_form.vat = "BE0477472701"
self.assertEqual(partner_form.name, partner.name)
self.assertEqual(partner_form.street, False)
self.assertEqual(partner_form.country_id.id, partner.country_id.id)
def test_non_eu_vat_change(self):
non_eu_country_id = self.env.ref("base.sc").id
partner = self.partner_model.create(
{
"name": "4",
"is_company": True,
"country_id": non_eu_country_id,
}
)
with Form(partner) as partner_form:
partner_form.vat = "GT1234567 - 1"
self.assertEqual(partner_form.name, partner.name)

1
requirements.txt

@ -1,3 +1,4 @@
# generated from manifests external_dependencies
email-validator
phonenumbers
python-stdnum

1
setup/partner_data_vies_populator/odoo/addons/partner_data_vies_populator

@ -0,0 +1 @@
../../../../partner_data_vies_populator

6
setup/partner_data_vies_populator/setup.py

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading…
Cancel
Save