Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.0] A better wizard for fiscal code generation. #569

Merged
merged 1 commit into from
Oct 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions l10n_it_fiscalcode/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Contributors
* Franco Tampieri <franco.tampieri@agilebg.com>
* Andrea Cometa <info@andreacometa.it>
* Andrea Gallina <a.gallina@apuliasoftware.it>
* Matteo Bilotta <mbilotta@linkgroup.it>


Maintainer
Expand Down
1 change: 1 addition & 0 deletions l10n_it_fiscalcode/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import model
Expand Down
9 changes: 7 additions & 2 deletions l10n_it_fiscalcode/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

# noinspection PyStatementEffect
{
'name': 'Italian Localisation - Fiscal Code',
'version': '11.0.1.0.0',
'version': '11.0.1.1.0',
'category': 'Localisation/Italy',
'author': "Odoo Italia Network, Odoo Community Association (OCA)",
'author': "Link IT s.r.l., "
"Apulia Software, "
"Odoo Italia Network, "
"Odoo Community Association (OCA)",
'website': 'https://odoo-community.org/',
'license': 'AGPL-3',
'depends': ['base_vat'],
Expand Down
9 changes: 9 additions & 0 deletions l10n_it_fiscalcode/migrations/11.0.1.1.0/pre-migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).


def migrate(cr, version):
if not version:
return

cr.execute("DROP VIEW IF EXISTS res_city_it_code_province;")
1 change: 1 addition & 0 deletions l10n_it_fiscalcode/model/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import res_partner
Expand Down
49 changes: 31 additions & 18 deletions l10n_it_fiscalcode/model/res_city_it_code.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import models, fields, tools


class ResCityItCode(models.Model):
#
# First...
# FIXME: URL in class description is no more useful...
#
# Visit:
# https://www.agenziaentrate.gov.it/wps/content/Nsilib/Nsi/
# Strumenti/Codici+attivita+e+tributo/Codici+territorio/
# ... and then click on "Consultazione Archivio Comuni e Stati esteri".
# You will be redirected on:
# https://www.agenziaentrate.gov.it/wps/content/nsilib/nsi/schede/
# fabbricatiterreni/archivio+comuni+e+stati+esteri/
# consultazione+archivio+comuni+stati+esteri
# Here, you can download the new and updated file CSV.
# (last update on 30/07/2018)
#
#
# ... BUT then...
# TODO: Find out how to import the new CSV without breaking existing data.
#
# The new CSV as a new structure:
# - some records have been deleted.
# - some columns no longer exist.
# - ...
# - ... and so on...
# - ...
#
#
# Good luck! ;)
#

"""
To create res.city.it.code.csv:
http://www.agenziaentrate.gov.it/wps/content/Nsilib/Nsi/Strumenti/
Expand Down Expand Up @@ -53,21 +84,3 @@ def init(self):
SELECT name, MAX(id) AS id FROM res_city_it_code
GROUP BY name)
""")


class ResCityItCodeProvince(models.Model):
_name = 'res.city.it.code.province'
_auto = False

name = fields.Char('Name', size=100)
town_name = fields.Char('Name', size=100)

def init(self):
tools.drop_view_if_exists(self.env.cr, self._table)
self.env.cr.execute(
"""
CREATE OR REPLACE VIEW res_city_it_code_province AS (
SELECT province AS name, name as town_name, MAX(id) AS id
FROM res_city_it_code
GROUP BY province, name)
""")
2 changes: 0 additions & 2 deletions l10n_it_fiscalcode/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
"access_res_city_it_code_group_user","res_city_it_code group_user","model_res_city_it_code","base.group_partner_manager",1,1,1,1
"access_res_city_it_code_distinct_group_all","res_city_it_code_distinct group_user_all","model_res_city_it_code_distinct",,1,0,0,0
"access_res_city_it_code_distinct_group_user","res_city_it_code_distinct group_user","model_res_city_it_code_distinct","base.group_partner_manager",1,1,1,1
"access_res_city_it_code_province_group_all","res_city_it_code_province group_user_all","model_res_city_it_code_province",,1,0,0,0
"access_res_city_it_code_province_group_user","res_city_it_code_province group_user","model_res_city_it_code_province","base.group_partner_manager",1,1,1,1
1 change: 1 addition & 0 deletions l10n_it_fiscalcode/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import test_fiscalcode
5 changes: 4 additions & 1 deletion l10n_it_fiscalcode/tests/test_fiscalcode.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo.tests.common import TransactionCase
Expand All @@ -9,7 +10,9 @@ class TestFiscalCode(TransactionCase):

def setUp(self):
super(TestFiscalCode, self).setUp()

self.partner = self.env.ref('base.res_partner_2')
self.rome_province = self.env.ref('base.state_it_rm')

def test_fiscalcode_compute(self):
wizard = self.env['wizard.compute.fc'].with_context(
Expand All @@ -19,7 +22,7 @@ def test_fiscalcode_compute(self):
'birth_date': '1984-06-04',
'sex': 'M',
'birth_city': 10048,
'birth_province': 10048,
'birth_province': self.rome_province.id
})
# ---- Compute FiscalCode
wizard.compute_fc()
Expand Down
1 change: 1 addition & 0 deletions l10n_it_fiscalcode/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import compute_fc
107 changes: 76 additions & 31 deletions l10n_it_fiscalcode/wizard/compute_fc.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,101 @@
# Copyright 2014 Associazione Odoo Italia (<http://www.odoo-italia.org>)
# Copyright 2016 Andrea Gallina (Apulia Software)
# Copyright © 2018 Matteo Bilotta (Link IT s.r.l.)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import datetime
import logging

from odoo import models, fields, api, _
from odoo.exceptions import UserError
import logging
import datetime
from odoo.osv import expression

_logger = logging.getLogger(__name__)

try:
from codicefiscale import build

except ImportError:
_logger.warning(
'codicefiscale library not found. '
'If you plan to use it, please install the codicefiscale library '
'from https://pypi.python.org/pypi/codicefiscale')
"codicefiscale library not found. "
"If you plan to use it, please install the codicefiscale library"
" from https://pypi.python.org/pypi/codicefiscale")


class WizardComputeFc(models.TransientModel):

_name = "wizard.compute.fc"
_name = 'wizard.compute.fc'
Byloth marked this conversation as resolved.
Show resolved Hide resolved
_description = "Compute Fiscal Code"
_rec_name = 'fiscalcode_surname'

fiscalcode_surname = fields.Char('Surname', size=64)
fiscalcode_firstname = fields.Char('First name', size=64)
birth_date = fields.Date('Date of birth')
birth_city = fields.Many2one(
'res.city.it.code.distinct', string='City of birth')
birth_province = fields.Many2one(
'res.city.it.code.province', string='Province')
sex = fields.Selection([
('M', 'Male'),
('F', 'Female'),
], "Sex")
fiscalcode_surname = fields.Char("Surname", required=True, size=64)
fiscalcode_firstname = fields.Char("First name", required=True, size=64)
birth_date = fields.Date("Date of birth", required=True)
birth_city = fields.Many2one('res.city.it.code.distinct',
required=True,
string="City of birth")
birth_province = fields.Many2one('res.country.state',
Byloth marked this conversation as resolved.
Show resolved Hide resolved
required=True,
string="Province")
sex = fields.Selection([('M', "Male"), ('F', "Female")],
required=True,
string="Sex")

@api.multi
@api.onchange('birth_city')
def onchange_birth_city(self):
self.ensure_one()
res = {}

it = self.env.ref('base.it').id
res = {
'domain': {'birth_province': [('country_id', '=', it)]},
'value': {'birth_province': False}
}

if self.birth_city:
ct = self.birth_city
res['domain'] = {
'birth_province': [('town_name', '=', ct.name)]
}
else:
res['domain'] = {'birth_province': []}
res['value'] = {'birth_province': ''}
# SMELLS: Add a foreign key in "res_city_it_code"
# instead using the weak link "code" <-> "province".
#
city_ids = self.env['res.city.it.code'] \
.search([('name', '=', self.birth_city.name)])
provinces = city_ids.mapped('province')
province_ids = self.env['res.country.state'] \
.search([('country_id', '=', it), ('code', 'in', provinces)])

res['domain']['birth_province'] = \
expression.AND([
res['domain']['birth_province'],
[('id', 'in', province_ids.ids)]
])

if len(province_ids) == 1:
res['value']['birth_province'] = province_ids.id

return res

@api.multi
@api.onchange('birth_province')
def onchange_birth_province(self):
self.ensure_one()

res = {'domain': {'birth_city': []}}

if not self.birth_city:
Byloth marked this conversation as resolved.
Show resolved Hide resolved
if self.birth_province:
# SMELLS: Add a foreign key in "res_city_it_code"
# instead using the weak link "code" <-> "province".
#
city_ids = self.env['res.city.it.code'] \
.search([('province', '=', self.birth_province.code)])
names = city_ids.mapped('name')
distinct_city_ids = self.env['res.city.it.code.distinct'] \
.search([('name', 'in', names)])

res['domain']['birth_city'] = \
expression.AND([
res['domain']['birth_city'],
[('id', 'in', distinct_city_ids.ids)]
])

return res

def _get_national_code(self, birth_city, birth_prov, birth_date):
Expand Down Expand Up @@ -88,11 +135,9 @@ def _get_national_code(self, birth_city, birth_prov, birth_date):
break
if newcts:
cities = newcts
return self._check_national_codes(
birth_city, birth_prov, birth_date, cities)
return self._check_national_codes(birth_date, cities)

def _check_national_codes(
self, birth_city, birth_prov, birth_date, cities):
def _check_national_codes(self, birth_date, cities):
nc = ''
dtcostvar = None
for ct in cities:
Expand Down Expand Up @@ -142,7 +187,7 @@ def compute_fc(self):
not f.birth_date or not f.birth_city or not f.sex):
raise UserError(_('One or more fields are missing'))
nat_code = self._get_national_code(
f.birth_city.name, f.birth_province.name, f.birth_date)
f.birth_city.name, f.birth_province.code, f.birth_date)
if not nat_code:
raise UserError(_('National code is missing'))
birth_date = datetime.datetime.strptime(f.birth_date, "%Y-%m-%d")
Expand Down
37 changes: 23 additions & 14 deletions l10n_it_fiscalcode/wizard/compute_fc_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,32 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Fiscal Code">
<h2>Individual Data</h2>
<group>
<group string="Individual Data">
<field name="fiscalcode_surname" default_focus="1"/>
<field name="fiscalcode_firstname"/>
<field name="sex"/>
<field name="birth_date"/>
<field name="birth_city"/>
<field name="birth_province" />
<group>
<field name="fiscalcode_surname" default_focus="1" />
<field name="fiscalcode_firstname" />
<field name="sex" widget="radio" />
</group>
<group>
<field name="birth_date" />
<field name="birth_city"
options="{'no_create': True,
'no_open': True}" />
<field name="birth_province"
options="{'no_create': True,
'no_open': True}" />
</group>
<newline/>
<footer>
<button name="compute_fc" type="object"
string="Compute" class="btn-primary"/>
<button string="Cancel" special="cancel"
class="btn-default"/>
</footer>
</group>
<footer>
<button class="btn-primary"
type="object"
name="compute_fc"
string="Compute" />
<button class="btn-default"
special="cancel"
string="Cancel" />
</footer>
</form>
</field>
</record>
Expand Down