# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Plating product family. import logging from odoo import api, fields, models, _ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class SaleOrder(models.Model): _inherit = 'sale.order' @api.onchange('partner_id') def _onchange_partner_id_invoice_strategy(self): """Auto-fill invoice strategy from customer defaults.""" if self.partner_id: default = self.env['fp.invoice.strategy.default'].search( [('partner_id', '=', self.partner_id.id)], limit=1, ) if default: self.x_fc_invoice_strategy = default.default_strategy self.x_fc_deposit_percent = default.default_deposit_percent if default.payment_term_id: self.payment_term_id = default.payment_term_id def action_confirm(self): """Override to check account hold and trigger invoice strategy.""" for order in self: # --- Account hold check --- if order.partner_id.x_fc_account_hold: is_manager = self.env.user.has_group( 'fusion_plating.group_fusion_plating_manager' ) if not is_manager: raise UserError(_( 'Cannot confirm — customer "%s" is on account hold.\n' 'Reason: %s\n\n' 'Contact a manager to override.' ) % (order.partner_id.name, order.partner_id.x_fc_account_hold_reason or 'No reason specified')) else: # Manager gets a warning in chatter but can proceed order.message_post( body=_( 'Warning: Customer "%s" is on account hold (reason: %s). ' 'Order confirmed by manager override.' ) % (order.partner_id.name, order.partner_id.x_fc_account_hold_reason or 'N/A'), ) res = super().action_confirm() # --- Invoice strategy automation --- for order in self: strategy = order.x_fc_invoice_strategy if not strategy: continue if strategy == 'deposit' and order.x_fc_deposit_percent: order._create_deposit_invoice() elif strategy == 'cod_prepay': order._create_full_invoice() return res def _create_deposit_invoice(self): """Create a deposit (down payment) invoice for the deposit percentage.""" self.ensure_one() percent = self.x_fc_deposit_percent if not percent or percent <= 0: return try: # Use Odoo's standard down payment mechanism wizard = self.env['sale.advance.payment.inv'].create({ 'advance_payment_method': 'percentage', 'amount': percent, }) wizard.with_context(active_ids=self.ids, active_model='sale.order').create_invoices() self.message_post( body=_('Deposit invoice (%.0f%%) created automatically — strategy: Deposit.') % percent, ) except Exception as e: _logger.warning('Failed to create deposit invoice for SO %s: %s', self.name, e) self.message_post( body=_('Failed to auto-create deposit invoice: %s. Create manually.') % str(e), ) def _create_full_invoice(self): """Create a full invoice immediately (COD/Prepay strategy).""" self.ensure_one() try: invoices = self._create_invoices() if invoices: self.message_post( body=_('Full invoice created automatically — strategy: COD / Prepay.'), ) except Exception as e: _logger.warning('Failed to create COD invoice for SO %s: %s', self.name, e) self.message_post( body=_('Failed to auto-create invoice: %s. Create manually.') % str(e), )