# -*- coding: utf-8 -*- import requests import re import urllib3 import logging from datetime import datetime from odoo import models, fields, api, _ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class ResPartner(models.Model): _inherit = 'res.partner' # 1. CAMPOS nif_ao = fields.Char(string="NIF Angola", copy=False) nif_ao_validated = fields.Boolean(string="NIF Validado", default=False, copy=False, readonly=True) nif_ao_state = fields.Char(string="Estado Fiscal (AGT)", readonly=True) nif_ao_contributor_type = fields.Char(string="Tipo de Contribuinte", readonly=True) nif_ao_inadimplente = fields.Char(string="Inadimplente", readonly=True) nif_ao_regime_iva = fields.Char(string="Regime de IVA", readonly=True) nif_ao_last_validation = fields.Datetime(string="Última Validação", readonly=True) nif_ao_validation_count = fields.Integer(string="Consultas", compute='_compute_nif_logs_count') # Contagem dos logs para mostrar no botão inteligente def _compute_nif_logs_count(self): for record in self: if self.env.get('nif.validation.log'): record.nif_ao_validation_count = self.env['nif.validation.log'].search_count([ ('partner_id', '=', record.id) ]) else: record.nif_ao_validation_count = 0 # Abre a janela do histórico def action_open_nif_logs(self): self.ensure_one() return { 'name': _('Logs de Consulta NIF'), 'type': 'ir.actions.act_window', 'res_model': 'nif.validation.log', 'view_mode': 'list,form', 'domain': [('partner_id', '=', self.id)], 'target': 'current', } # NOVO: Função para apagar o histórico de consultas deste cliente def action_clear_nif_logs(self): self.ensure_one() if self.env.get('nif.validation.log'): logs = self.env['nif.validation.log'].search([('partner_id', '=', self.id)]) logs.unlink() # Apaga os registos da base de dados return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': _('Histórico Apagado'), 'message': _('Todo o histórico de consultas deste NIF foi apagado.'), 'type': 'warning', } } # 2. LÓGICA DE EXTRAÇÃO (API AGT) @api.onchange('nif_ao') def _onchange_nif_ao_fetch_agt(self): if not self.nif_ao or len(self.nif_ao.strip()) < 9: return nif = self.nif_ao.strip() urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) url = f"https://portaldocontribuinte.minfin.gov.ao/consultar-nif-do-contribuinte?nif={nif}" headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/122.0.0.0'} try: _logger.info(">>> A consultar AGT para NIF: %s", nif) response = requests.get(url, headers=headers, timeout=15, verify=False) if response.status_code == 200 and response.text: html = response.text clean_text = re.sub(r'<[^>]+>', ' ', html) clean_text = re.sub(r'\s+', ' ', clean_text).strip() nome_m = re.search(r'Nome:\s*(.*?)\s*Tipo:', clean_text, re.IGNORECASE) tipo_m = re.search(r'Tipo:\s*(.*?)\s*Estado:', clean_text, re.IGNORECASE) est_m = re.search(r'Estado:\s*(.*?)\s*Inadimplente:', clean_text, re.IGNORECASE) inad_m = re.search(r'Inadimplente:\s*(.*?)\s*Regime de IVA:', clean_text, re.IGNORECASE) iva_m = re.search(r'Regime de IVA:\s*(.*?)\s*Residente Fiscal', clean_text, re.IGNORECASE) if nome_m: self.name = nome_m.group(1).strip() if tipo_m: self.nif_ao_contributor_type = tipo_m.group(1).strip() if est_m: self.nif_ao_state = est_m.group(1).strip() if inad_m: self.nif_ao_inadimplente = inad_m.group(1).strip() if iva_m: self.nif_ao_regime_iva = iva_m.group(1).strip() self.nif_ao_validated = True self.nif_ao_last_validation = fields.Datetime.now() except Exception as e: _logger.error("Erro na busca: %s", str(e)) # 3. AÇÃO DO BOTÃO "CONSULTAR" (Agora regista os Logs a sério!) def action_validate_nif(self): self.ensure_one() if not self.nif_ao: raise UserError(_("Por favor, preencha o campo NIF Angola primeiro.")) # 1. Faz a pesquisa no portal da AGT self._onchange_nif_ao_fetch_agt() # 2. Se a pesquisa correu bem, cria o registo no Histórico (Log) if self.nif_ao_validated: if self.env.get('nif.validation.log'): self.env['nif.validation.log'].create({ 'partner_id': self.id, 'nif': self.nif_ao, 'state': 'Sucesso', 'raw_response': f"Nome: {self.name} | Estado: {self.nif_ao_state} | IVA: {self.nif_ao_regime_iva}" }) return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': _('Sucesso'), 'message': _('Dados da AGT consultados com sucesso e registados no histórico.'), 'type': 'success', } } else: raise UserError(_("Não foi possível aceder à AGT. Verifique o NIF."))