Skip to content

Commit b82d69b

Browse files
[IMP] l10n_br_cnpj_search: add a wizard for verification of the data
1 parent c1e12ae commit b82d69b

18 files changed

+266
-60
lines changed

l10n_br_cnpj_search/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
22

33
from . import models
4+
from . import wizard

l10n_br_cnpj_search/__manifest__.py

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
],
1717
"data": [
1818
"security/ir.model.access.csv",
19+
"wizard/partner_cnpj_search_wizard.xml",
1920
"views/res_partner_view.xml",
2021
"views/res_company_view.xml",
2122
"views/res_config_settings_view.xml",

l10n_br_cnpj_search/models/l10n_br_base_party_mixin.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class PartyMixin(models.AbstractModel):
1414
def search_cnpj(self):
1515
"""Search CNPJ by the chosen API"""
1616
if not self.cnpj_cpf:
17-
raise UserError(_("Por favor insira o CNPJ"))
17+
raise UserError(_("Please enter your CNPJ"))
1818

1919
if self.cnpj_validation_disabled():
2020
raise UserError(
@@ -35,6 +35,34 @@ def search_cnpj(self):
3535
values["company_type"] = "company"
3636
self.write(values)
3737

38+
def action_open_cnpj_search_wizard(self, mockresponse=False):
39+
if not self.cnpj_cpf:
40+
raise UserError(_("Please enter your CNPJ"))
41+
if self.cnpj_validation_disabled():
42+
raise UserError(
43+
_(
44+
"It is necessary to activate the option to validate de CNPJ to use"
45+
" this functionality."
46+
)
47+
)
48+
if self._name == "res.partner":
49+
default_partner_id = self.id
50+
else:
51+
default_partner_id = self.partner_id.id
52+
53+
return {
54+
"name": "Search Data by CNPJ",
55+
"type": "ir.actions.act_window",
56+
"res_model": "partner.search.wizard",
57+
"view_type": "form",
58+
"view_mode": "form",
59+
"context": {
60+
"default_partner_id": default_partner_id,
61+
"mockresponse": mockresponse,
62+
},
63+
"target": "new",
64+
}
65+
3866
@api.model
3967
def cnpj_validation_disabled(self):
4068
cnpj_validation_disabled = (

l10n_br_cnpj_search/models/res_partner.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright 2022 KMEE - Luis Felipe Mileo
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
33

4-
54
from odoo import fields, models
65

76

l10n_br_cnpj_search/security/ir.model.access.csv

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
22
access_l10n_br_cnpj_search_webservice,access_l10n_br_cnpj_search_webservice,model_l10n_br_cnpj_search_webservice_abstract,base.group_user,1,1,1,1
33
"l10n_br_fiscal_partner_profile_user","l10n_br_fiscal.partner_profile","l10n_br_fiscal.model_l10n_br_fiscal_partner_profile","base.group_user",1,0,0,0
44
"l10n_br_fiscal_cnae","l10n_br_fiscal.cnae","l10n_br_fiscal.model_l10n_br_fiscal_cnae","base.group_user",1,0,0,0
5+
access_partner_search_wizard,res_partner_wizard,model_partner_search_wizard,base.group_user,1,1,1,1

l10n_br_cnpj_search/static/description/index.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
12
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
23
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
34
<head>
@@ -366,7 +367,7 @@ <h1 class="title">Brazilian Localization CNPJ Search</h1>
366367
!! This file is generated by oca-gen-addon-readme !!
367368
!! changes will be overwritten. !!
368369
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
369-
!! source digest: sha256:9f660a5cf5d9e7c903559a6bf11c459e96b9a6f6e78a9b48941c54d030774060
370+
!! source digest: sha256:b75c0c19af2d63fd70d67fbb130cbbf4f9a4393f3f048abb85d387672d1eac92
370371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
371372
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/l10n-brazil/tree/14.0/l10n_br_cnpj_search"><img alt="OCA/l10n-brazil" src="https://img.shields.io/badge/github-OCA%2Fl10n--brazil-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/l10n-brazil-14-0/l10n-brazil-14-0-l10n_br_cnpj_search"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/l10n-brazil&amp;target_branch=14.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372373
<p>Módulo que adiciona um botão para preencher automaticamente os campos de um partner a partir do seu CNPJ.

l10n_br_cnpj_search/tests/test_receitaws.py

+25-15
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,51 @@ def setUp(self):
1515
super().setUp()
1616

1717
self.set_param("cnpj_provider", "receitaws")
18+
self.partner_model = self.env["res.partner"]
1819

1920
def test_receita_ws_success(self):
20-
kilian = self.model.create({"name": "Kilian", "cnpj_cpf": "44.356.113/0001-08"})
21+
kilian = self.partner_model.create(
22+
{
23+
"name": "Kilian",
24+
"cnpj_cpf": "44.356.113/0001-08",
25+
}
26+
)
27+
context = {"default_partner_id": kilian.id}
2128

22-
kilian._onchange_cnpj_cpf()
23-
kilian.search_cnpj()
29+
wizard = self.env["partner.search.wizard"].with_context(context).create({})
30+
self.assertEqual(wizard.legal_name, "Kilian Macedo Melcher 08777131460")
31+
self.assertEqual(wizard.name, "Kilian Macedo Melcher 08777131460")
32+
self.assertEqual(wizard.email, "kilian.melcher@gmail.com")
33+
self.assertEqual(wizard.street_name, "Rua Luiza Bezerra Motta")
34+
self.assertEqual(wizard.street2, "Bloco E;Apt 302")
35+
self.assertEqual(wizard.street_number, "950")
36+
self.assertEqual(wizard.zip, "58.410-410")
37+
self.assertEqual(wizard.district, "Catole")
38+
self.assertEqual(wizard.phone, "(83) 8665-0905")
39+
self.assertEqual(wizard.state_id.code, "PB")
40+
self.assertEqual(wizard.city_id.name, "Campina Grande")
41+
self.assertEqual(wizard.equity_capital, 3000)
42+
time.sleep(2)
43+
wizard.action_update_partner()
2444

25-
self.assertEqual(kilian.company_type, "company")
2645
self.assertEqual(kilian.legal_name, "Kilian Macedo Melcher 08777131460")
27-
self.assertEqual(kilian.name, "Kilian Macedo Melcher 08777131460")
28-
self.assertEqual(kilian.email, "kilian.melcher@gmail.com")
2946
self.assertEqual(kilian.street_name, "Rua Luiza Bezerra Motta")
30-
self.assertEqual(kilian.street2, "Bloco E;Apt 302")
31-
self.assertEqual(kilian.street_number, "950")
32-
self.assertEqual(kilian.zip, "58.410-410")
3347
self.assertEqual(kilian.district, "Catole")
3448
self.assertEqual(kilian.phone, "(83) 8665-0905")
35-
self.assertEqual(kilian.state_id.code, "PB")
36-
self.assertEqual(kilian.city_id.name, "Campina Grande")
37-
self.assertEqual(kilian.equity_capital, 3000)
38-
self.assertEqual(kilian.cnae_main_id.code, "4751-2/01")
3949

4050
def test_receita_ws_fail(self):
4151
invalido = self.model.create({"name": "invalido", "cnpj_cpf": "00000000000000"})
4252
invalido._onchange_cnpj_cpf()
4353

44-
time.sleep(2) # Pause
54+
time.sleep(2)
4555
with self.assertRaises(ValidationError):
4656
invalido.search_cnpj()
4757

4858
def test_receita_ws_multiple_phones(self):
4959
isla = self.model.create({"name": "Isla", "cnpj_cpf": "92.666.056/0001-06"})
5060
isla._onchange_cnpj_cpf()
5161

52-
time.sleep(2) # Pause
62+
time.sleep(2)
5363
isla.search_cnpj()
5464

5565
self.assertEqual(isla.name.strip(), "Isla Sementes Ltda.")

l10n_br_cnpj_search/views/res_company_view.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<div class="o_row" colspan="1">
1818
<field name="cnpj_cpf" />
1919
<button
20-
name="search_cnpj"
20+
name="action_open_cnpj_search_wizard"
2121
type="object"
2222
class="btn-sm btn-link mb4 fa fa-search oe_edit_only oe_inline"
2323
aria-label="Pesquisar CNPJ"

l10n_br_cnpj_search/views/res_partner_view.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<div class="o_row" colspan="4">
2020
<field name="cnpj_cpf" nolabel="1" />
2121
<button
22-
name="search_cnpj"
22+
name="action_open_cnpj_search_wizard"
2323
type="object"
2424
attrs="{'invisible':
2525
[
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import partner_cnpj_search_wizard
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from erpbrasil.base.fiscal import cnpj_cpf
2+
from erpbrasil.base.misc import punctuation_rm
3+
from requests import get
4+
5+
from odoo import api, fields, models
6+
7+
8+
class PartnerCnpjSearchWizard(models.TransientModel):
9+
_name = "partner.search.wizard"
10+
11+
partner_id = fields.Many2one(comodel_name="res.partner")
12+
provider_name = fields.Char()
13+
cnpj_cpf = fields.Char()
14+
legal_name = fields.Char()
15+
name = fields.Char()
16+
inscr_est = fields.Char()
17+
zip = fields.Char()
18+
street_name = fields.Char()
19+
street_number = fields.Char()
20+
street2 = fields.Char()
21+
district = fields.Char()
22+
state_id = fields.Many2one(comodel_name="res.country.state")
23+
city_id = fields.Many2one(
24+
comodel_name="res.city",
25+
domain="[('state_id', '=', state_id)]",
26+
)
27+
country_id = fields.Many2one(comodel_name="res.country")
28+
phone = fields.Char()
29+
mobile = fields.Char()
30+
email = fields.Char()
31+
legal_nature = fields.Char()
32+
currency_id = fields.Many2one(
33+
comodel_name="res.currency",
34+
default=lambda self: self.env.ref("base.BRL"),
35+
)
36+
equity_capital = fields.Monetary(currency_field="currency_id")
37+
cnae_main_id = fields.Many2one(comodel_name="l10n_br_fiscal.cnae")
38+
cnae_secondary_ids = fields.Many2many(
39+
comodel_name="l10n_br_fiscal.cnae",
40+
relation="wizard_fiscal_cnae_rel",
41+
column1="company_id",
42+
column2="cnae_id",
43+
)
44+
45+
@api.onchange("cnpj_cpf")
46+
def _onchange_cnpj_cpf(self):
47+
self.cnpj_cpf = cnpj_cpf.formata(str(self.cnpj_cpf))
48+
49+
def _get_partner_values(self, cnpj_cpf, mockresponse=False):
50+
webservice = self.env["l10n_br_cnpj_search.webservice.abstract"]
51+
provider_name = webservice.get_provider()
52+
response = get(
53+
webservice.get_api_url(cnpj_cpf), headers=webservice.get_headers()
54+
)
55+
data = webservice.validate(response)
56+
values = webservice.import_data(data)
57+
values["provider_name"] = provider_name
58+
values["cnpj_cpf"] = cnpj_cpf
59+
return values
60+
61+
def default_get(self, fields):
62+
res = super().default_get(fields)
63+
partner_id = self._context.get("default_partner_id")
64+
partner_model = self.env["res.partner"]
65+
partner = partner_model.browse(partner_id)
66+
cnpj_cpf = punctuation_rm(partner.cnpj_cpf)
67+
mockresponse = self._context.get("mockresponse", False)
68+
values = self._get_partner_values(cnpj_cpf, mockresponse=mockresponse)
69+
res.update(values)
70+
return res
71+
72+
def action_update_partner(self):
73+
values_to_update = {
74+
"legal_name": self.legal_name,
75+
"name": self.name,
76+
"inscr_est": self.inscr_est,
77+
"zip": self.zip,
78+
"street_name": self.street_name,
79+
"street_number": self.street_number,
80+
"street2": self.street2,
81+
"district": self.district,
82+
"state_id": self.state_id.id,
83+
"city_id": self.city_id.id,
84+
"country_id": self.country_id.id,
85+
"phone": self.phone,
86+
"mobile": self.mobile,
87+
"email": self.email,
88+
"legal_nature": self.legal_nature,
89+
"equity_capital": self.equity_capital,
90+
"cnae_main_id": self.cnae_main_id,
91+
"cnae_secondary_ids": self.cnae_secondary_ids,
92+
}
93+
non_empty_values = {
94+
key: value for key, value in values_to_update.items() if value
95+
}
96+
if non_empty_values:
97+
# Update partner only if there are non-empty values
98+
self.partner_id.write(non_empty_values)
99+
return {"type": "ir.actions.act_window_close"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<odoo>
2+
<record id="res_partner_wizard_view" model="ir.ui.view">
3+
<field name="name">res_partner_wizard</field>
4+
<field name="model">partner.search.wizard</field>
5+
<field name="arch" type="xml">
6+
<form class="o_form_sheet">
7+
<div class="alert alert-info" role="alert" style="margin-bottom: 0px;">
8+
CNPJ data was obtained through the webservice: <field
9+
name="provider_name"
10+
readonly="1"
11+
/>
12+
</div>
13+
14+
<group>
15+
<group name="Identification" string="Identification">
16+
<field name="name" />
17+
<field name="legal_name" />
18+
<field name="cnpj_cpf" readonly="1" string="CNPJ" />
19+
<field name="inscr_est" string="IE" />
20+
</group>
21+
22+
<group name="Contacts" string="Contacts">
23+
<field name="phone" />
24+
<field name="mobile" />
25+
<field name="email" />
26+
</group>
27+
</group>
28+
29+
<group>
30+
<group name="Address" string="Address">
31+
<field name="zip" />
32+
<field name="street_name" />
33+
<field name="street_number" />
34+
<field name="street2" />
35+
<field name="district" />
36+
<field name="state_id" />
37+
<field name="city_id" />
38+
</group>
39+
40+
<group name="Other Information" string="Other Information">
41+
<field name="legal_nature" />
42+
<field name="equity_capital" widget="monetary" />
43+
<field name="cnae_main_id" string="Main CNAE" />
44+
<field
45+
name="cnae_secondary_ids"
46+
widget="many2many_tags"
47+
string="Secundary CNAE"
48+
/>
49+
<field name="currency_id" invisible="1" />
50+
</group>
51+
</group>
52+
53+
<footer>
54+
<button
55+
string="Update Partner"
56+
type="object"
57+
class="oe_highlight"
58+
name="action_update_partner"
59+
/>
60+
<button string="Close" class="oe_link" special="cancel" />
61+
</footer>
62+
</form>
63+
</field>
64+
</record>
65+
</odoo>

l10n_br_ie_search/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
22

33
from . import models
4+
from . import wizard

l10n_br_ie_search/models/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
from . import sefaz_webservice
44
from . import sintegra_webservice
55
from . import res_config_settings
6-
from . import l10n_br_base_party_mixin

l10n_br_ie_search/tests/test_sefaz.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ def test_sefaz(self):
110110
"certificate_ecnpj_id": self.cert.id,
111111
}
112112
)
113-
time.sleep(1) # to avoid too many requests
113+
time.sleep(1)
114114
dummy._onchange_cnpj_cpf()
115-
dummy.ie_search(self.retorno)
116115

116+
wizard_data = {"default_partner_id": dummy.id, "mockresponse": self.retorno}
117+
dummy = self.env["partner.search.wizard"].with_context(wizard_data).create({})
117118
self.assertEqual(dummy.inscr_est, "528388258640")

l10n_br_ie_search/tests/test_sintegra.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ def set_param(self, param_name, param_value):
7777
def test_sintegra(self):
7878
dummy = self.model.create({"name": "Dummy", "cnpj_cpf": "06990590000123"})
7979

80-
time.sleep(2) # to avoid too many requests
80+
time.sleep(2)
8181
dummy._onchange_cnpj_cpf()
82-
dummy.ie_search(self.retorno)
8382

83+
wizard_data = {"default_partner_id": dummy.id, "mockresponse": self.retorno}
84+
dummy = self.env["partner.search.wizard"].with_context(wizard_data).create({})
8485
self.assertEqual(dummy.inscr_est, "149848403115")

l10n_br_ie_search/wizard/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import extend_partner_cnpj_search_wizard

0 commit comments

Comments
 (0)