4
4
##############################################################################
5
5
from odoo import _ , api , fields , models
6
6
from odoo .exceptions import UserError
7
+ from odoo .tools .float_utils import float_compare
7
8
8
9
9
10
class SaleOrder (models .Model ):
10
11
_inherit = "sale.order"
11
12
12
- delivery_status = fields .Selection (
13
- selection_add = [
14
- ("no" , "Nothing to Deliver" ),
15
- ],
16
- readonly = True ,
17
- default = "no" ,
18
- )
19
13
force_delivery_status = fields .Selection (
20
14
[
21
- ("no" , "Nothing to Deliver" ),
22
15
("full" , "Fully Delivered" ),
23
16
],
24
17
tracking = True ,
@@ -43,17 +36,66 @@ def action_cancel(self):
43
36
)
44
37
return super ().action_cancel ()
45
38
46
- @api .depends ("picking_ids" , "picking_ids.state" , "force_delivery_status" )
39
+ @api .depends (
40
+ "picking_ids" ,
41
+ "picking_ids.state" ,
42
+ "force_delivery_status" ,
43
+ "order_line.qty_delivered" ,
44
+ "order_line.product_uom_qty" ,
45
+ )
47
46
def _compute_delivery_status (self ):
47
+ """
48
+ Compute delivery status considering both storable products and services.
49
+ """
48
50
super ()._compute_delivery_status ()
51
+ precision = self .env ["decimal.precision" ].precision_get ("Product Unit of Measure" )
49
52
for order in self :
50
- if not order .picking_ids or all (p .state == "cancel" for p in order .picking_ids ):
51
- order .delivery_status = "no"
52
- continue
53
53
if order .force_delivery_status :
54
54
order .delivery_status = order .force_delivery_status
55
55
continue
56
56
57
+ storable_lines = order .order_line .filtered (
58
+ lambda l : l .product_id .type == "consu" and l .product_id .is_storable
59
+ )
60
+ service_lines = order .order_line .filtered (lambda l : l .product_id .type == "service" )
61
+
62
+ if not storable_lines and not service_lines :
63
+ order .delivery_status = False
64
+ continue
65
+
66
+ if not service_lines :
67
+ continue
68
+
69
+ service_fully_delivered = service_partially_delivered = True
70
+ for line in service_lines :
71
+ delivered , ordered = line .qty_delivered , line .product_uom_qty
72
+ if float_compare (delivered , ordered , precision_digits = precision ) < 0 :
73
+ service_fully_delivered = False
74
+ if float_compare (delivered , 0.0 , precision_digits = precision ) == 0 :
75
+ service_partially_delivered = False
76
+ break
77
+
78
+ service_status = (
79
+ "full" if service_fully_delivered else ("partial" if service_partially_delivered else "pending" )
80
+ )
81
+
82
+ if not storable_lines :
83
+ order .delivery_status = service_status
84
+ continue
85
+
86
+ storable_status = order .delivery_status
87
+ if storable_status == "full" and service_status == "full" :
88
+ order .delivery_status = "full"
89
+ elif (
90
+ storable_status == "partial"
91
+ or storable_status == "full"
92
+ or service_status == "partial"
93
+ or service_status == "full"
94
+ ):
95
+ order .delivery_status = "partial"
96
+ else :
97
+ order .delivery_status = "pending"
98
+
57
99
def write (self , vals ):
58
100
self .check_force_delivery_status (vals )
59
101
return super ().write (vals )
0 commit comments