diff --git a/fusion_plating/fusion_plating_configurator/tests/test_charge_tax_lot.py b/fusion_plating/fusion_plating_configurator/tests/test_charge_tax_lot.py index 3909c110..38a06ddd 100644 --- a/fusion_plating/fusion_plating_configurator/tests/test_charge_tax_lot.py +++ b/fusion_plating/fusion_plating_configurator/tests/test_charge_tax_lot.py @@ -28,3 +28,19 @@ class TestChargeTaxLot(TransactionCase): self.assertEqual(ct.default_amount, 75.0) cid, cname = self.env['fp.additional.charge.type'].name_create('Setup') 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) diff --git a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard.py b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard.py index 062cb8bf..bef86e7a 100644 --- a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard.py +++ b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard.py @@ -401,65 +401,41 @@ class FpDirectOrderWizard(models.Model): # ---- Computes ---- @api.depends( - 'line_ids.line_subtotal', 'line_ids.quantity', 'line_ids.unit_price', - 'line_ids.tax_ids', + 'charge_amount', 'tooling_charge', + 'tax_id', 'partner_id', 'currency_id', ) 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 - Express form's totals card mirrors what the eventual SO will show - once the operator hits Confirm. The tooling charge is added at the - wizard level here AND pushed as an actual sale.order.line at - action_create_order time (so it carries into the invoice). + The order-level ``tax_id`` is applied once to (subtotal + charge), + where charge = ``charge_amount`` (legacy ``tooling_charge`` as + fallback). The charge is also pushed as an actual sale.order.line + at action_create_order time (so it carries into the invoice). """ 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 - for line in rec.line_ids: - line_pre_tax = (line.quantity or 0) * (line.unit_price or 0.0) - subtotal += line_pre_tax - if line.tax_ids and line_pre_tax: - taxes_res = line.tax_ids.compute_all( - line.unit_price or 0.0, - currency=rec.currency_id, - 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 rec.tax_id and (subtotal + charge): + res = rec.tax_id.compute_all( + subtotal + charge, + currency=rec.currency_id, + quantity=1, + product=None, + partner=rec.partner_id or None, ) - if first_taxed_line: - 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'] - ) + tax_total = res['total_included'] - res['total_excluded'] rec.total_subtotal = subtotal 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_line_count = len(rec.line_ids)