feat(configurator): SO-create applies one tax to all lines + typed charge line
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -326,6 +326,9 @@ class SaleOrderLine(models.Model):
|
||||
'pair, falling back to the part\'s default range. Prints '
|
||||
'verbatim on the cert, packing slip, and invoice.',
|
||||
)
|
||||
x_fc_is_lot_priced = fields.Boolean(string='Lot Priced')
|
||||
x_fc_lot_total = fields.Monetary(
|
||||
string='Lot Total', currency_field='currency_id')
|
||||
|
||||
# ---- Express Orders per-line flags (2026-05-26) ----
|
||||
# Mirror fp.direct.order.line.{customer_line_ref, masking_enabled, bake_instructions}
|
||||
|
||||
@@ -813,7 +813,7 @@ class FpDirectOrderWizard(models.Model):
|
||||
'x_fc_internal_notes': self.internal_notes or False,
|
||||
# material_process is a Many2One since 19.0.22.1.0 — pass .id
|
||||
'x_fc_material_process': self.material_process.id if self.material_process else False,
|
||||
'x_fc_tooling_charge': self.tooling_charge or 0.0,
|
||||
'x_fc_tooling_charge': self.charge_amount or self.tooling_charge or 0.0,
|
||||
'pricelist_id': self.pricelist_id.id if self.pricelist_id else False,
|
||||
'validity_date': self.validity_date or False,
|
||||
'order_line': [],
|
||||
@@ -895,32 +895,29 @@ class FpDirectOrderWizard(models.Model):
|
||||
# When blank, Odoo will compute taxes from the product
|
||||
# defaults at SO-line save time (the standard behaviour).
|
||||
# NB. Odoo 19 renamed the SO line field to tax_ids.
|
||||
'tax_ids': ([(6, 0, line.tax_ids.ids)]
|
||||
if line.tax_ids else False),
|
||||
'tax_ids': ([(6, 0, self.tax_id.ids)]
|
||||
if self.tax_id else False),
|
||||
'x_fc_is_lot_priced': line.is_lot_priced,
|
||||
'x_fc_lot_total': line.lot_total or 0.0,
|
||||
}))
|
||||
|
||||
# 4b. Tooling charge — surface as a real sale.order.line so it
|
||||
# carries through SO.amount_total + invoice naturally, instead of
|
||||
# sitting orphaned on the SO header. Tax: inherit from the first
|
||||
# part line that has taxes set (best proxy for "the customer's
|
||||
# standard tax rate"); falls back to product defaults if no line
|
||||
# has taxes yet.
|
||||
if self.tooling_charge:
|
||||
tooling_taxes = False
|
||||
first_taxed = next(
|
||||
(l for l in self.line_ids if l.tax_ids), False,
|
||||
)
|
||||
if first_taxed:
|
||||
tooling_taxes = [(6, 0, first_taxed.tax_ids.ids)]
|
||||
# 4b. Additional charge — one typed line, taxed by the order-level
|
||||
# tax. The charge type's name labels the line; charge_amount with
|
||||
# legacy tooling_charge fallback for in-flight drafts.
|
||||
charge_amt = self.charge_amount or self.tooling_charge or 0.0
|
||||
if charge_amt:
|
||||
charge_name = (self.charge_type_id.name
|
||||
if self.charge_type_id else _('Additional Charge'))
|
||||
so_vals['order_line'].append((0, 0, {
|
||||
'product_id': product.id,
|
||||
'name': _('Tooling Charge'),
|
||||
'name': charge_name,
|
||||
'product_uom_qty': 1.0,
|
||||
'price_unit': self.tooling_charge,
|
||||
'price_unit': charge_amt,
|
||||
'x_fc_internal_description': _(
|
||||
'One-time tooling fee added via Express Orders.'
|
||||
'Additional charge added via Express Orders.'
|
||||
),
|
||||
'tax_ids': tooling_taxes,
|
||||
'tax_ids': ([(6, 0, self.tax_id.ids)]
|
||||
if self.tax_id else False),
|
||||
}))
|
||||
|
||||
# 5. Create — stays in draft / quotation. Sub 1: user reviews
|
||||
|
||||
Reference in New Issue
Block a user