feat(configurator): totals = one tax on (subtotal + charge)

This commit is contained in:
gsinghpal
2026-05-29 21:37:00 -04:00
parent a07a5f931a
commit f8929eb686
2 changed files with 37 additions and 45 deletions

View File

@@ -28,3 +28,19 @@ class TestChargeTaxLot(TransactionCase):
self.assertEqual(ct.default_amount, 75.0) self.assertEqual(ct.default_amount, 75.0)
cid, cname = self.env['fp.additional.charge.type'].name_create('Setup') cid, cname = self.env['fp.additional.charge.type'].name_create('Setup')
self.assertTrue(cid) self.assertTrue(cid)
# ----- Task 3: totals -----
def _make_wizard(self, **kw):
vals = {'partner_id': self.partner.id}
vals.update(kw)
return self.env['fp.direct.order.wizard'].create(vals)
def test_tax_applies_on_subtotal_plus_charge(self):
wiz = self._make_wizard(charge_amount=100.0, tax_id=self.tax13.id)
self.env['fp.direct.order.line'].create({
'wizard_id': wiz.id, 'quantity': 1, 'unit_price': 50.0,
})
wiz.invalidate_recordset()
self.assertEqual(wiz.total_subtotal, 50.0)
self.assertAlmostEqual(wiz.total_tax, 19.5, places=2)
self.assertAlmostEqual(wiz.total_amount, 169.5, places=2)

View File

@@ -401,65 +401,41 @@ class FpDirectOrderWizard(models.Model):
# ---- Computes ---- # ---- Computes ----
@api.depends( @api.depends(
'line_ids.line_subtotal',
'line_ids.quantity', 'line_ids.quantity',
'line_ids.unit_price', 'line_ids.unit_price',
'line_ids.tax_ids', 'charge_amount',
'tooling_charge', 'tooling_charge',
'tax_id',
'partner_id', 'partner_id',
'currency_id', 'currency_id',
) )
def _compute_totals(self): def _compute_totals(self):
"""Roll up subtotal / tax / grand total across lines + tooling. """Roll up subtotal / tax / grand total across lines + charge.
Each line's taxes are computed via account.tax.compute_all so the The order-level ``tax_id`` is applied once to (subtotal + charge),
Express form's totals card mirrors what the eventual SO will show where charge = ``charge_amount`` (legacy ``tooling_charge`` as
once the operator hits Confirm. The tooling charge is added at the fallback). The charge is also pushed as an actual sale.order.line
wizard level here AND pushed as an actual sale.order.line at at action_create_order time (so it carries into the invoice).
action_create_order time (so it carries into the invoice).
""" """
for rec in self: for rec in self:
subtotal = 0.0 subtotal = sum(
(l.quantity or 0) * (l.unit_price or 0.0)
for l in rec.line_ids
)
charge = rec.charge_amount or rec.tooling_charge or 0.0
tax_total = 0.0 tax_total = 0.0
for line in rec.line_ids: if rec.tax_id and (subtotal + charge):
line_pre_tax = (line.quantity or 0) * (line.unit_price or 0.0) res = rec.tax_id.compute_all(
subtotal += line_pre_tax subtotal + charge,
if line.tax_ids and line_pre_tax: currency=rec.currency_id,
taxes_res = line.tax_ids.compute_all( quantity=1,
line.unit_price or 0.0, product=None,
currency=rec.currency_id, partner=rec.partner_id or None,
quantity=line.quantity or 0,
product=None,
partner=rec.partner_id or None,
)
tax_total += (
taxes_res['total_included']
- taxes_res['total_excluded']
)
# Tooling charge: pick the tax set from the FIRST line that
# has one (best proxy for the customer's standard rate). If
# no line has taxes set yet, tooling is shown untaxed in the
# preview; the eventual SO line will apply product defaults.
tooling = rec.tooling_charge or 0.0
if tooling:
first_taxed_line = next(
(l for l in rec.line_ids if l.tax_ids), False,
) )
if first_taxed_line: tax_total = res['total_included'] - res['total_excluded']
tooling_res = first_taxed_line.tax_ids.compute_all(
tooling,
currency=rec.currency_id,
quantity=1,
product=None,
partner=rec.partner_id or None,
)
tax_total += (
tooling_res['total_included']
- tooling_res['total_excluded']
)
rec.total_subtotal = subtotal rec.total_subtotal = subtotal
rec.total_tax = tax_total rec.total_tax = tax_total
rec.total_amount = subtotal + tax_total + tooling rec.total_amount = subtotal + charge + tax_total
rec.total_qty = sum(rec.line_ids.mapped('quantity')) rec.total_qty = sum(rec.line_ids.mapped('quantity'))
rec.total_line_count = len(rec.line_ids) rec.total_line_count = len(rec.line_ids)