This commit is contained in:
gsinghpal
2026-04-29 03:35:33 -04:00
parent 6ac6d24da6
commit a2fe1fcbcc
61 changed files with 4655 additions and 667 deletions

View File

@@ -3,6 +3,8 @@
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from datetime import timedelta
from odoo import _, api, fields, models
from odoo.exceptions import UserError
@@ -220,23 +222,39 @@ class FpDirectOrderWizard(models.Model):
self._apply_strategy_payment_term()
return
# Legacy partner-field defaults (pre-Sub-5).
if 'x_fc_default_invoice_strategy' in self.partner_id._fields:
self.invoice_strategy = self.partner_id.x_fc_default_invoice_strategy or False
self.deposit_percent = self.partner_id.x_fc_default_deposit_percent or 0.0
# Partner-level plating defaults — primary cascade. Customers
# migrated to the new partner fields skip the legacy lookup below.
partner = self.partner_id
if partner.x_fc_default_invoice_strategy:
self.invoice_strategy = partner.x_fc_default_invoice_strategy
if partner.x_fc_default_deposit_percent:
self.deposit_percent = partner.x_fc_default_deposit_percent
if partner.x_fc_default_delivery_method:
self.delivery_method = partner.x_fc_default_delivery_method
# Deadline auto-fill — anchored to planned_start_date with today
# as fallback. Honours explicit deadlines the user already typed.
anchor = self.planned_start_date or fields.Date.context_today(self)
if (partner.x_fc_default_internal_deadline_days
and not self.internal_deadline):
self.internal_deadline = (
anchor + timedelta(days=partner.x_fc_default_internal_deadline_days)
)
if (partner.x_fc_default_customer_deadline_days
and not self.customer_deadline):
self.customer_deadline = (
anchor + timedelta(days=partner.x_fc_default_customer_deadline_days)
)
# Addresses.
addrs = self.partner_id.address_get(['invoice', 'delivery'])
self.partner_invoice_id = addrs.get('invoice') or self.partner_id.id
self.partner_shipping_id = addrs.get('delivery') or self.partner_id.id
addrs = partner.address_get(['invoice', 'delivery'])
self.partner_invoice_id = addrs.get('invoice') or partner.id
self.partner_shipping_id = addrs.get('delivery') or partner.id
# Per-customer invoice strategy default (fp.invoice.strategy.default).
# Pull strategy + deposit even when payment_term_id is empty — the
# previous condition `if isd and isd.payment_term_id` silently
# skipped the strategy fill for net-terms customers without
# explicit terms configured.
# Legacy fallback: fp.invoice.strategy.default (kept for sites
# mid-migration). Only fills gaps the partner fields didn't cover.
isd = self.env['fp.invoice.strategy.default'].search(
[('partner_id', '=', self.partner_id.id)], limit=1,
[('partner_id', '=', partner.id)], limit=1,
)
term = False
if isd:
@@ -245,8 +263,8 @@ class FpDirectOrderWizard(models.Model):
if not self.deposit_percent:
self.deposit_percent = isd.default_deposit_percent or 0.0
term = isd.payment_term_id
if not term and self.partner_id.property_payment_term_id:
term = self.partner_id.property_payment_term_id
if not term and partner.property_payment_term_id:
term = partner.property_payment_term_id
self.payment_term_id = term or False
# Re-apply strategy → terms mapping after partner switch.
@@ -271,6 +289,29 @@ class FpDirectOrderWizard(models.Model):
"""Map the strategy onto sensible payment terms."""
self._apply_strategy_payment_term()
@api.onchange('planned_start_date')
def _onchange_planned_start_date(self):
"""Recompute deadlines from partner offsets when start moves.
Runs only if the partner has offsets configured AND deadlines
are still blank — typing a manual deadline locks it.
"""
if not self.partner_id or not self.planned_start_date:
return
partner = self.partner_id
if (partner.x_fc_default_internal_deadline_days
and not self.internal_deadline):
self.internal_deadline = (
self.planned_start_date
+ timedelta(days=partner.x_fc_default_internal_deadline_days)
)
if (partner.x_fc_default_customer_deadline_days
and not self.customer_deadline):
self.customer_deadline = (
self.planned_start_date
+ timedelta(days=partner.x_fc_default_customer_deadline_days)
)
def _apply_strategy_payment_term(self):
"""Mapping rule:
- cod_prepay → Immediate Payment
@@ -435,6 +476,12 @@ class FpDirectOrderWizard(models.Model):
[('default_code', '=', 'FP-SERVICE')], limit=1,
)
if not product:
# Seed the product with the company's default sale tax so the
# customer's fiscal position has something to RE-MAP. Without
# this, lines come out tax-free regardless of how the customer's
# fiscal position is configured (fiscal positions only re-map
# existing taxes; they don't manufacture them).
default_sale_tax = self.env.company.account_sale_tax_id
product = self.env['product.product'].create({
'name': 'Plating Service',
'default_code': 'FP-SERVICE',
@@ -442,7 +489,14 @@ class FpDirectOrderWizard(models.Model):
'list_price': 0,
'sale_ok': True,
'purchase_ok': False,
'taxes_id': [(6, 0, default_sale_tax.ids)] if default_sale_tax else False,
})
elif not product.taxes_id and self.env.company.account_sale_tax_id:
# Self-heal: pre-existing FP-SERVICE without taxes (created in
# an earlier version) silently produced tax-free lines. Top up
# with the company default sale tax so customer fiscal positions
# can re-map correctly.
product.taxes_id = [(6, 0, self.env.company.account_sale_tax_id.ids)]
# 3. Build SO header
so_vals = {