Trust-Code/odoo-brasil

View on GitHub
br_zip/models/br_zip.py

Summary

Maintainability
D
2 days
Test Coverage
# -*- coding: utf-8 -*-
# © 2012  Renato Lima - Akretion
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import re
import logging
import requests

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


_logger = logging.getLogger(__name__)


class BrZip(models.Model):
    _name = 'br.zip'
    _description = u'CEP'
    _rec_name = 'zip'

    zip = fields.Char('CEP', size=8, required=True)
    street_type = fields.Char('Tipo', size=26)
    street = fields.Char('Logradouro', size=72)
    district = fields.Char('Bairro', size=72)
    country_id = fields.Many2one('res.country', 'Country')
    state_id = fields.Many2one(
        'res.country.state', 'Estado',
        domain="[('country_id','=',country_id)]")
    city_id = fields.Many2one(
        'res.state.city', 'Cidade',
        required=True, domain="[('state_id','=',state_id)]")

    def set_domain(self, country_id=False, state_id=False,
                   city_id=False, district=False,
                   street=False, zip_code=False):
        domain = []
        if zip_code:
            new_zip = re.sub('[^0-9]', '', zip_code or '')
            domain.append(('zip', '=', new_zip))
        else:
            if not state_id or not city_id or \
                    len(street or '') == 0:
                raise UserError(
                    u'Necessário informar Estado, município e logradouro')

            if country_id:
                domain.append(('country_id', '=', country_id))
            if state_id:
                domain.append(('state_id', '=', state_id))
            if city_id:
                domain.append(('city_id', '=', city_id))
            if district:
                domain.append(('district', 'ilike', district))
            if street:
                domain.append(('street', 'ilike', street))

        return domain

    def set_result(self, zip_obj=None):
        if zip_obj:
            zip_code = zip_obj.zip
            if len(zip_code) == 8:
                zip_code = '%s-%s' % (zip_code[0:5], zip_code[5:8])
            result = {
                'country_id': zip_obj.country_id.id,
                'state_id': zip_obj.state_id.id,
                'city_id': zip_obj.city_id.id,
                'district': zip_obj.district,
                'street': ((zip_obj.street_type or '') +
                           ' ' + (zip_obj.street or '')) if
                zip_obj.street_type else (zip_obj.street or ''),
                'zip': zip_code,
            }
        else:
            result = {}
        return result

    def zip_search_multi(self, country_id=False,
                         state_id=False, city_id=False,
                         district=False, street=False, zip_code=False):
        domain = self.set_domain(
            country_id=country_id,
            state_id=state_id,
            city_id=city_id,
            district=district,
            street=street,
            zip_code=zip_code)
        zip_ids = self.search(domain)
        if len(zip_ids) == 0:
            zip_code = re.sub('[^0-9]', '', zip_code or '')
            if zip_code and len(zip_code) == 8:
                self._search_by_cep(zip_code)
            elif zip_code:
                raise UserError(u'Digite o cep corretamente')
            else:
                self._search_by_address(state_id, city_id, street)

            return self.search(domain)
        else:
            return zip_ids

    def _search_by_cep(self, zip_code):
        try:
            url_viacep = 'http://viacep.com.br/ws/' + \
                zip_code + '/json/unicode/'
            obj_viacep = requests.get(url_viacep)
            res = obj_viacep.json()
            if not res.get('erro', False):
                city = self.env['res.state.city'].search(
                    [('ibge_code', '=', res['ibge'][2:]),
                     ('state_id.code', '=', res['uf'])])

                self.env['br.zip'].create(
                    {'zip': re.sub('[^0-9]', '', res['cep']),
                     'street': res['logradouro'],
                     'district': res['bairro'],
                     'country_id': city.state_id.country_id.id,
                     'state_id': city.state_id.id,
                     'city_id': city.id})

        except Exception as e:
            _logger.error(e.message, exc_info=True)

    def _search_by_address(self, state_id, city_id, street):
        try:
            city = self.env['res.state.city'].browse(city_id)
            url_viacep = 'http://viacep.com.br/ws/' + city.state_id.code + \
                '/' + city.name + '/' + street + '/json/unicode/'
            obj_viacep = requests.get(url_viacep)
            results = obj_viacep.json()
            if results:
                for res in results:
                    city = self.env['res.state.city'].search(
                        [('ibge_code', '=', res['ibge'][2:]),
                         ('state_id.code', '=', res['uf'])])

                    self.env['br.zip'].create(
                        {'zip': re.sub('[^0-9]', '', res['cep']),
                         'street': res['logradouro'],
                         'district': res['bairro'],
                         'country_id': city.state_id.country_id.id,
                         'state_id': city.state_id.id,
                         'city_id': city.id})

        except Exception as e:
            _logger.error(e.message, exc_info=True)

    @api.multi
    def search_by_zip(self, zip_code):
        zip_ids = self.zip_search_multi(zip_code=zip_code)
        if len(zip_ids) == 1:
            return self.set_result(zip_ids[0])
        else:
            raise UserError(_(u'Nenhum CEP encontrado'))

    @api.multi
    def seach_by_address(self, obj, country_id=False, state_id=False,
                         city_id=False, district=False, street=False):

        zip_ids = self.zip_search_multi(
            country_id=country_id, state_id=state_id,
            city_id=city_id, district=district, street=street)

        if len(zip_ids) == 1:
            res = self.set_result(zip_ids[0])
            return res
        else:
            if len(zip_ids) > 1:
                obj_zip_result = self.env['br.zip.result']
                zip_ids = obj_zip_result.map_to_zip_result(
                    zip_ids, obj._name, obj.id)

                return self.create_wizard(
                    obj._name,
                    obj.id,
                    country_id=obj.country_id.id,
                    state_id=obj.state_id.id,
                    city_id=obj.city_id.id,
                    district=obj.district,
                    street=obj.street,
                    zip_code=obj.zip,
                    zip_ids=[z.id for z in zip_ids]
                )
            else:
                raise UserError(_(u'Nenhum registro encontrado'))

    def create_wizard(self, object_name, address_id, country_id=False,
                      state_id=False, city_id=False,
                      district=False, street=False, zip_code=False,
                      zip_ids=False):
        context = dict(self.env.context)
        context.update({
            'zip': zip_code,
            'street': street,
            'district': district,
            'country_id': country_id,
            'state_id': state_id,
            'city_id': city_id,
            'zip_ids': zip_ids,
            'address_id': address_id,
            'object_name': object_name})

        result = {
            'name': u'Zip Search',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'br.zip.search',
            'view_id': False,
            'context': context,
            'type': 'ir.actions.act_window',
            'target': 'new',
            'nodestroy': True,
        }

        return result