# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) import re import logging from odoo import api, fields, models, _ _logger = logging.getLogger(__name__) class FusionFaxRC(models.Model): """Extend fusion.fax with contact matching, smart buttons, forward fax, and send-new-fax actions.""" _inherit = 'fusion.fax' invoice_count = fields.Integer( string='Invoices', compute='_compute_partner_counts', ) sale_order_count = fields.Integer( string='Sales Orders', compute='_compute_partner_counts', ) @api.depends('partner_id') def _compute_partner_counts(self): for rec in self: if rec.partner_id: partner = rec.partner_id.commercial_partner_id or rec.partner_id partner_ids = (partner | partner.child_ids).ids rec.sale_order_count = self.env['sale.order'].search_count( [('partner_id', 'in', partner_ids)], ) rec.invoice_count = self.env['account.move'].search_count( [('partner_id', 'in', partner_ids), ('move_type', 'in', ('out_invoice', 'out_refund'))], ) else: rec.sale_order_count = 0 rec.invoice_count = 0 @api.model_create_multi def create(self, vals_list): for vals in vals_list: if not vals.get('partner_id'): partner = self._match_fax_partner( vals.get('fax_number', ''), vals.get('sender_number', ''), vals.get('direction', ''), ) if partner: vals['partner_id'] = partner.id return super().create(vals_list) @api.model def _match_fax_partner(self, fax_number, sender_number, direction): """Match a fax to a contact by fax number, phone, or mobile.""" search_number = sender_number if direction == 'inbound' else fax_number if not search_number: return False cleaned = self._normalize_fax_phone(search_number) if not cleaned or len(cleaned) < 7: return False Partner = self.env['res.partner'] if 'x_ff_fax_number' in Partner._fields: partners = Partner.search( [('x_ff_fax_number', '!=', False)], order='customer_rank desc, write_date desc', ) for p in partners: if self._normalize_fax_phone(p.x_ff_fax_number) == cleaned: return p phone_fields = [f for f in ('phone', 'mobile') if f in Partner._fields] if phone_fields: domain = ['|'] * (len(phone_fields) - 1) for f in phone_fields: domain.append((f, '!=', False)) partners = Partner.search(domain, order='customer_rank desc, write_date desc') for p in partners: for f in phone_fields: val = p[f] if val and self._normalize_fax_phone(val) == cleaned: return p return False @staticmethod def _normalize_fax_phone(number): return re.sub(r'\D', '', number or '')[-10:] if number else '' # ────────────────────────────────────────────────────────── # Smart button actions # ────────────────────────────────────────────────────────── def action_view_contact(self): self.ensure_one() if not self.partner_id: return return { 'type': 'ir.actions.act_window', 'res_model': 'res.partner', 'res_id': self.partner_id.id, 'view_mode': 'form', 'target': 'current', } def action_view_sale_orders(self): self.ensure_one() if not self.partner_id: return partner = self.partner_id.commercial_partner_id or self.partner_id partner_ids = (partner | partner.child_ids).ids return { 'type': 'ir.actions.act_window', 'name': _('Sales Orders - %s') % self.partner_id.name, 'res_model': 'sale.order', 'view_mode': 'list,form', 'domain': [('partner_id', 'in', partner_ids)], 'target': 'current', } def action_view_invoices(self): self.ensure_one() if not self.partner_id: return partner = self.partner_id.commercial_partner_id or self.partner_id partner_ids = (partner | partner.child_ids).ids return { 'type': 'ir.actions.act_window', 'name': _('Invoices - %s') % self.partner_id.name, 'res_model': 'account.move', 'view_mode': 'list,form', 'domain': [('partner_id', 'in', partner_ids), ('move_type', 'in', ('out_invoice', 'out_refund'))], 'target': 'current', } # ────────────────────────────────────────────────────────── # Forward Fax (received fax -> send to someone else) # ────────────────────────────────────────────────────────── def action_forward_fax(self): """Open Send Fax wizard with this fax's documents pre-attached.""" self.ensure_one() attachment_ids = self.document_ids.sorted('sequence').mapped('attachment_id').ids ctx = { 'default_document_source_fax_id': self.id, 'forward_attachment_ids': attachment_ids, } return { 'type': 'ir.actions.act_window', 'name': _('Forward Fax - %s') % self.name, 'res_model': 'fusion_faxes.send.fax.wizard', 'view_mode': 'form', 'target': 'new', 'context': ctx, } # ────────────────────────────────────────────────────────── # Send New Fax (pre-fill contact from current fax) # ────────────────────────────────────────────────────────── def action_send_new_fax(self): """Open Send Fax wizard pre-filled with this fax's contact info.""" self.ensure_one() ctx = {} if self.partner_id: ctx['default_partner_id'] = self.partner_id.id fax_num = '' if self.direction == 'inbound': fax_num = self.sender_number or self.fax_number else: fax_num = self.fax_number if fax_num: ctx['default_fax_number'] = fax_num return { 'type': 'ir.actions.act_window', 'name': _('Send New Fax'), 'res_model': 'fusion_faxes.send.fax.wizard', 'view_mode': 'form', 'target': 'new', 'context': ctx, }