@@ -285,6 +285,67 @@ def test_landed_costs_by_line_and_by_total(self):
285285 doc_after_total_update .fiscal_amount_total , 2776.48 , places = 2
286286 )
287287
288+ def test_fiscal_amount_recompute_on_delivery_cost_write (self ):
289+ """Verify fiscal_amount_untaxed recomputes after direct delivery cost write.
290+
291+ When amount_freight_value (or insurance/other) is written on the document,
292+ the ORM protects all co-computed _compute_fiscal_amount fields during the
293+ inverse call. This means the trigger tree propagation from line field
294+ changes back to fiscal_amount_untaxed is blocked by the protection
295+ mechanism. Without an explicit env.add_to_compute in
296+ _distribute_amount_to_lines, fiscal_amount_untaxed remains stale —
297+ especially when the trigger tree has extra hops due to addon-added computed
298+ fields on the lines.
299+ """
300+ self .env .user .groups_id |= self .env .ref ("l10n_br_fiscal.group_user" )
301+ product1 = self .env .ref ("product.product_product_6" )
302+ product2 = self .env .ref ("product.product_product_7" )
303+
304+ self .company .delivery_costs = "total"
305+ doc_form = Form (self .env ["l10n_br_fiscal.document" ])
306+ doc_form .company_id = self .company
307+ doc_form .partner_id = self .env .ref ("l10n_br_base.res_partner_cliente1_sp" )
308+ doc_form .fiscal_operation_id = self .env .ref ("l10n_br_fiscal.fo_venda" )
309+
310+ with doc_form .fiscal_line_ids .new () as line_form :
311+ line_form .product_id = product1
312+ line_form .fiscal_operation_line_id = self .env .ref (
313+ "l10n_br_fiscal.fo_venda_venda"
314+ )
315+ line_form .price_unit = 1000.0
316+ line_form .quantity = 2.0 # price_gross = 2000
317+
318+ with doc_form .fiscal_line_ids .new () as line_form :
319+ line_form .product_id = product2
320+ line_form .fiscal_operation_line_id = self .env .ref (
321+ "l10n_br_fiscal.fo_venda_venda"
322+ )
323+ line_form .price_unit = 500.0
324+ line_form .quantity = 1.0 # price_gross = 500
325+
326+ doc = doc_form .save ()
327+ self .assertAlmostEqual (doc .fiscal_amount_untaxed , 2500.0 )
328+
329+ # Write delivery costs directly via write() — triggers inverse methods
330+ # inside the ORM's protecting() context. Unlike Form.save(), write()
331+ # does not automatically flush pending computations, exposing the
332+ # staleness when add_to_compute is missing.
333+ doc .write ({"amount_freight_value" : 50.0 })
334+
335+ # Freight distributed proportionally (80%/20%): line1=40, line2=10
336+ # fiscal_amount_untaxed = (2000+40) + (500+10) = 2550
337+ self .assertAlmostEqual (doc .fiscal_amount_untaxed , 2550.0 )
338+
339+ doc .write ({"amount_insurance_value" : 25.0 })
340+ # Insurance distributed: line1=20, line2=5
341+ # fiscal_amount_untaxed = (2000+40+20) + (500+10+5) = 2575
342+ self .assertAlmostEqual (doc .fiscal_amount_untaxed , 2575.0 )
343+
344+ doc .write ({"amount_other_value" : 10.0 })
345+ # Other distributed: line1=8, line2=2
346+ # fiscal_amount_untaxed = (2000+40+20+8) + (500+10+5+2) = 2585
347+ self .assertAlmostEqual (doc .fiscal_amount_untaxed , 2585.0 )
348+
288349 def test_difal_calculation (self ):
289350 partner = self .env .ref ("l10n_br_base.res_partner_cliente5_pe" )
290351 partner .ind_ie_dest = "9"
0 commit comments