1010
1111
1212class SaleOrderLine (models .Model ):
13- _inherit = "sale.order.line"
13+ _name = "sale.order.line"
14+ _inherit = ["sale.order.line" , "triple.discount.mixin" ]
1415
1516 # core discount field is now a computed field
1617 # based on the 3 discounts defined below.
@@ -20,38 +21,19 @@ class SaleOrderLine(models.Model):
2021 # the main discount is 24.7885 % (and not 24.79)
2122 discount = fields .Float (
2223 string = "Total Disc (%)" ,
23- compute = "_compute_discount" ,
24- inverse = "_inverse_discount" ,
2524 store = True ,
26- readonly = True ,
27- digits = None ,
25+ compute = "_compute_discount" ,
26+ compute_sudo = True ,
27+ precompute = True ,
2828 )
2929 discount1 = fields .Float (
30- compute = "_compute_discounts" ,
31- precompute = True ,
32- store = True ,
33- readonly = False ,
3430 string = "Disc. 1 (%)" ,
3531 digits = "Discount" ,
36- default = 0.0 ,
37- )
38- discount2 = fields .Float (
39- compute = "_compute_discounts" ,
40- precompute = True ,
32+ compute = "_compute_discount1" ,
4133 store = True ,
42- readonly = False ,
43- string = "Disc. 2 (%)" ,
44- digits = "Discount" ,
45- default = 0.0 ,
46- )
47- discount3 = fields .Float (
48- compute = "_compute_discounts" ,
34+ compute_sudo = True ,
4935 precompute = True ,
50- store = True ,
5136 readonly = False ,
52- string = "Disc. 3 (%)" ,
53- digits = "Discount" ,
54- default = 0.0 ,
5537 )
5638 discounting_type = fields .Selection (
5739 selection = [("additive" , "Additive" ), ("multiplicative" , "Multiplicative" )],
@@ -88,7 +70,9 @@ def _get_final_discount(self):
8870
8971 def _additive_discount (self ):
9072 self .ensure_one ()
91- discount = sum (self [x ] or 0.0 for x in self ._discount_fields ())
73+ discount = sum (
74+ self [x ] or 0.0 for x in self ._get_multiple_discount_field_names ()
75+ )
9276 if discount <= 0 :
9377 return 0
9478 elif discount >= 100 :
@@ -97,67 +81,67 @@ def _additive_discount(self):
9781
9882 def _multiplicative_discount (self ):
9983 self .ensure_one ()
100- discounts = [1 - (self [x ] or 0.0 ) / 100 for x in self ._discount_fields ()]
101- final_discount = 1
102- for discount in discounts :
103- final_discount *= discount
104- return 100 - final_discount * 100
105-
106- @api .model
107- def _discount_fields (self ):
108- return ["discount1" , "discount2" , "discount3" ]
84+ return self ._get_aggregated_multiple_discounts (
85+ [self [x ] for x in self ._get_multiple_discount_field_names ()]
86+ )
10987
110- @api .depends ("discount1" , "discount2" , "discount3" , "discounting_type" )
88+ @api .depends (
89+ lambda self : self ._get_multiple_discount_field_names ()
90+ + ["product_id" , "product_uom" , "product_uom_qty" ]
91+ )
11192 def _compute_discount (self ):
93+ # Base Odoo just continues instead of assigning to 0 in this case
94+ # but we depend on the super() value resetting to a discount unpolluted
95+ # by the extra fields before taking them into account
96+ for line in self :
97+ if not (line .pricelist_item_id and line .pricelist_item_id ._show_discount ()):
98+ line .discount = 0
11299 res = super ()._compute_discount ()
113- for rec in self :
114- rec .discount = rec ._get_final_discount ()
100+ if self .env .context .get ("skip_triple_discount" ):
101+ return res
102+ for line in self :
103+ line .discount = line ._get_final_discount ()
115104 return res
116105
117- def _inverse_discount (self ):
118- for rec in self :
119- rec .update ({"discount1" : rec .discount , "discount2" : 0 , "discount3" : 0 })
120-
121- @api .depends ("discount" )
122- def _compute_discounts (self ):
123- # We intentionally call super to avoid triggering the full compute logic,
124- # which would recalculate 'discount' from the three discount fields
125- # At this stage, those fields may not be updated yet, and calling
126- # _compute_discount() directly would overwrite the current value
127- # calling super ensures the cache is coherent before applying the inverse
128- super ()._compute_discount ()
129- self ._inverse_discount ()
130- return True
131-
132- _sql_constraints = [
133- (
134- "discount1_limit" ,
135- "CHECK (discount1 <= 100.0)" ,
136- "Discount 1 must be lower or equal than 100%." ,
137- ),
138- (
139- "discount2_limit" ,
140- "CHECK (discount2 <= 100.0)" ,
141- "Discount 2 must be lower or equal than 100%." ,
142- ),
143- (
144- "discount3_limit" ,
145- "CHECK (discount3 <= 100.0)" ,
146- "Discount 3 must be lower or equal than 100%." ,
147- ),
148- ]
106+ @api .depends ("product_id" , "product_uom" , "product_uom_qty" )
107+ def _compute_discount1 (self ):
108+ # Calculate the original super()s discount and drag it to discount1
109+ # This is primarily for the field to visually update when creating new lines
110+ # rather than updating itself in the create() after you save
111+ # Since we aren't in the actual compute, this shouldn't actually save any
112+ # values to .discount
113+ with self .env .protecting (
114+ [self .env ["sale.order.line" ]._fields ["discount" ]], self
115+ ):
116+ self .with_context (skip_triple_discount = True )._compute_discount ()
117+ for line in self :
118+ line .discount1 = line .discount
149119
150120 def _prepare_invoice_line (self , ** kwargs ):
151121 """
152122 Inherit this method to bring
153123 more discount fields to the invoice lines
154124 """
155125 res = super ()._prepare_invoice_line (** kwargs )
156- res .update (
157- {
158- "discount1" : self .discount1 ,
159- "discount2" : self .discount2 ,
160- "discount3" : self .discount3 ,
161- }
162- )
126+ res .pop ("discount" , None )
127+ if self .discounting_type == "multiplicative" :
128+ res .update (
129+ {
130+ "discount1" : self .discount1 ,
131+ "discount2" : self .discount2 ,
132+ "discount3" : self .discount3 ,
133+ }
134+ )
135+ else :
136+ res .update ({"discount1" : self .discount })
163137 return res
138+
139+ @api .model_create_multi
140+ def create (self , vals_list ):
141+ order_lines = super ().create (vals_list )
142+ lines_to_discount = self .env ["sale.order.line" ]
143+ for line , vals in zip (order_lines , vals_list , strict = True ):
144+ if "discount" in vals and vals ["discount" ] == 0 :
145+ lines_to_discount |= line
146+ lines_to_discount .write ({"discount1" : 0.0 , "discount2" : 0.0 , "discount3" : 0.0 })
147+ return order_lines
0 commit comments