# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Plating product family. from odoo import api, models, _ from odoo.exceptions import UserError class AccountMove(models.Model): _inherit = 'account.move' @api.model_create_multi def create(self, vals_list): """Auto-inherit payment terms from the customer when missing. Customers usually have a default `property_payment_term_id` (Net-30, Net-60, COD…). When an invoice is created without terms, the due date silently defaults to "immediate" — wrong for almost every B2B customer. Pull the partner's terms in before super so the invoice is born with the right schedule. """ Partner = self.env['res.partner'] for vals in vals_list: if vals.get('move_type') in ('out_invoice', 'out_refund'): if not vals.get('invoice_payment_term_id') and vals.get('partner_id'): partner = Partner.browse(vals['partner_id']) if partner.property_payment_term_id: vals['invoice_payment_term_id'] = partner.property_payment_term_id.id return super().create(vals_list) def action_post(self): """Block post when: • customer is on account hold (existing rule), or • the invoice has no payment term (auto-fill missed it AND partner had no default — accountant must pick one). """ for move in self: if move.move_type in ('out_invoice', 'out_refund') and move.partner_id: if move.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 post invoice — customer "%s" is on account hold.\n' 'Reason: %s\n\n' 'Contact a manager to override.' ) % (move.partner_id.name, move.partner_id.x_fc_account_hold_reason or 'No reason specified')) if not move.invoice_payment_term_id: raise UserError(_( 'Cannot post invoice "%s" — no payment terms set.\n\n' 'Pick payment terms (Net-30, COD, etc.) on the invoice, ' 'or set a default on the customer "%s" so future ' 'invoices inherit it automatically.' ) % (move.name or move.display_name, move.partner_id.name)) return super().action_post()