chore(plating): de-dash shipped code + intake-neutral customer emails
Replace em-dashes and en-dashes with hyphens across 789 shipped source files (py/xml/js/scss) so the delivered module reads as human-written; em-dashes had become a recognizable AI-generated tell. Internal .md dev notes are excluded. The WO-sticker mojibake strippers keep their dash search targets (now written — / –). No logic changes: comments and display strings only; validated with py_compile + lxml parse. Rewrite the 7 customer notification emails to be intake-neutral (ship-in / drop-off / pickup) and repair-aware, and fix the Shipped email documents line (packing slip vs bill of lading; certificate only when issued). Subjects use a hyphen separator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ _logger = logging.getLogger(__name__)
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
|
||||
# Explicit related field — dotted refs like `partner_id.x_fc_account_hold`
|
||||
# Explicit related field - dotted refs like `partner_id.x_fc_account_hold`
|
||||
# in `invisible=` modifiers are fragile in Odoo 19 (the related field
|
||||
# has to be in the record cache for the evaluator). Surfacing it as a
|
||||
# plain field on sale.order makes the banner condition deterministic.
|
||||
@@ -67,7 +67,7 @@ class SaleOrder(models.Model):
|
||||
|
||||
@api.onchange('x_fc_planned_start_date')
|
||||
def _onchange_planned_start_date_deadlines(self):
|
||||
"""Recompute deadlines when planned start changes — without it
|
||||
"""Recompute deadlines when planned start changes - without it
|
||||
the partner offsets would only fire on partner_id change."""
|
||||
self._fp_recompute_default_deadlines()
|
||||
|
||||
@@ -104,14 +104,14 @@ class SaleOrder(models.Model):
|
||||
# whole downstream chain (CoC, BoL, invoice) from going
|
||||
# out unreferenced. The PO# is on `client_order_ref`
|
||||
# (Odoo standard) AND mirrored to `x_fc_po_number`
|
||||
# (FP-specific) — accept either as filled.
|
||||
# (FP-specific) - accept either as filled.
|
||||
#
|
||||
# Two escape hatches for real-world cases:
|
||||
# * x_fc_po_pending — estimator flag: "PO coming later".
|
||||
# * x_fc_po_pending - estimator flag: "PO coming later".
|
||||
# Confirms the order without a PO number and schedules
|
||||
# a chase activity for x_fc_po_expected_date so sales
|
||||
# doesn't forget to chase the paperwork.
|
||||
# * x_fc_po_override — manager waiver: "proceed without
|
||||
# * x_fc_po_override - manager waiver: "proceed without
|
||||
# a formal PO (handshake deal)". Permanent.
|
||||
po_set = bool(order.client_order_ref) or bool(
|
||||
getattr(order, 'x_fc_po_number', False)
|
||||
@@ -120,11 +120,11 @@ class SaleOrder(models.Model):
|
||||
po_override = bool(getattr(order, 'x_fc_po_override', False))
|
||||
if not po_set and not po_pending and not po_override:
|
||||
raise UserError(_(
|
||||
'Cannot confirm SO "%(so)s" — Customer PO# is required.\n\n'
|
||||
'Cannot confirm SO "%(so)s" - Customer PO# is required.\n\n'
|
||||
'Set the customer\'s purchase order number in the '
|
||||
'"Customer Reference" field (or x_fc_po_number) before '
|
||||
'confirming. If the customer will provide the PO '
|
||||
'later, tick "PO Pending" and set "PO Expected By" — '
|
||||
'later, tick "PO Pending" and set "PO Expected By" - '
|
||||
'the order will confirm with a follow-up activity to '
|
||||
'chase the paperwork. A Plating Manager can also set '
|
||||
'"PO Override" for handshake deals.'
|
||||
@@ -133,14 +133,14 @@ class SaleOrder(models.Model):
|
||||
# --- Account hold check ---
|
||||
# Hold lives on the commercial_partner (the company). Resolve
|
||||
# through that so a hold on the parent applies to every child
|
||||
# contact too — typical case is "all of Acme is on hold", not
|
||||
# contact too - typical case is "all of Acme is on hold", not
|
||||
# "specifically the AP clerk's contact card".
|
||||
hold_partner = order.partner_id.commercial_partner_id
|
||||
if hold_partner.x_fc_account_hold:
|
||||
is_manager = self.env['res.partner']._fp_user_can_override_account_hold()
|
||||
if not is_manager:
|
||||
raise UserError(_(
|
||||
'Cannot confirm — customer "%s" is on account hold.\n'
|
||||
'Cannot confirm - customer "%s" is on account hold.\n'
|
||||
'Reason: %s\n\n'
|
||||
'Contact a manager to override.'
|
||||
) % (hold_partner.name,
|
||||
@@ -164,7 +164,7 @@ class SaleOrder(models.Model):
|
||||
if not getattr(order, 'x_fc_po_pending', False):
|
||||
continue
|
||||
if getattr(order, 'x_fc_po_number', False) or order.client_order_ref:
|
||||
continue # PO already set — nothing to chase
|
||||
continue # PO already set - nothing to chase
|
||||
from datetime import timedelta
|
||||
expected = (
|
||||
order.x_fc_po_expected_date
|
||||
@@ -197,7 +197,7 @@ class SaleOrder(models.Model):
|
||||
order._create_full_invoice()
|
||||
elif strategy == 'progress' and order.x_fc_progress_initial_percent:
|
||||
order._create_progress_initial_invoice()
|
||||
# 'net_terms' — no action on confirm; invoiced when delivery is marked delivered
|
||||
# 'net_terms' - no action on confirm; invoiced when delivery is marked delivered
|
||||
|
||||
return res
|
||||
|
||||
@@ -212,7 +212,7 @@ class SaleOrder(models.Model):
|
||||
return
|
||||
try:
|
||||
# The wizard's sale_order_ids default reads active_ids AT CREATE
|
||||
# time — context must be set on .with_context(), not on the
|
||||
# time - context must be set on .with_context(), not on the
|
||||
# subsequent create_invoices() call.
|
||||
wizard = self.env['sale.advance.payment.inv'].with_context(
|
||||
active_ids=self.ids,
|
||||
@@ -224,7 +224,7 @@ class SaleOrder(models.Model):
|
||||
})
|
||||
wizard.create_invoices()
|
||||
self.message_post(
|
||||
body=_('Deposit invoice (%.0f%%) created — strategy: Deposit.') % percent,
|
||||
body=_('Deposit invoice (%.0f%%) created - strategy: Deposit.') % percent,
|
||||
)
|
||||
except Exception as e:
|
||||
_logger.warning('Failed to create deposit invoice for SO %s: %s', self.name, e)
|
||||
@@ -239,7 +239,7 @@ class SaleOrder(models.Model):
|
||||
invoices = self._create_invoices()
|
||||
if invoices:
|
||||
self.message_post(
|
||||
body=_('Full invoice created — strategy: COD / Prepay.'),
|
||||
body=_('Full invoice created - strategy: COD / Prepay.'),
|
||||
)
|
||||
except Exception as e:
|
||||
_logger.warning('Failed to create COD invoice for SO %s: %s', self.name, e)
|
||||
@@ -248,7 +248,7 @@ class SaleOrder(models.Model):
|
||||
)
|
||||
|
||||
def _create_progress_initial_invoice(self):
|
||||
"""Progress Billing — first invoice at SO confirm.
|
||||
"""Progress Billing - first invoice at SO confirm.
|
||||
|
||||
Uses Odoo's down-payment mechanism to bill the initial percentage.
|
||||
The remainder is billed on delivery via `_create_final_balance_invoice`.
|
||||
@@ -269,7 +269,7 @@ class SaleOrder(models.Model):
|
||||
wizard.create_invoices()
|
||||
self.message_post(
|
||||
body=_(
|
||||
'Progress invoice — initial %.0f%% created — strategy: Progress Billing. '
|
||||
'Progress invoice - initial %.0f%% created - strategy: Progress Billing. '
|
||||
'Final balance will be invoiced on delivery.'
|
||||
) % percent,
|
||||
)
|
||||
@@ -288,7 +288,7 @@ class SaleOrder(models.Model):
|
||||
"""
|
||||
self.ensure_one()
|
||||
if self.x_fc_final_invoice_id:
|
||||
return self.x_fc_final_invoice_id # Already invoiced — don't double
|
||||
return self.x_fc_final_invoice_id # Already invoiced - don't double
|
||||
if self.invoice_status == 'invoiced':
|
||||
return False # Nothing more to bill
|
||||
try:
|
||||
@@ -300,7 +300,7 @@ class SaleOrder(models.Model):
|
||||
).get(self.x_fc_invoice_strategy, self.x_fc_invoice_strategy)
|
||||
self.message_post(
|
||||
body=_(
|
||||
'Final invoice created on delivery — strategy: %s.'
|
||||
'Final invoice created on delivery - strategy: %s.'
|
||||
) % strategy_label,
|
||||
)
|
||||
return invoices
|
||||
|
||||
Reference in New Issue
Block a user