-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsale.py
183 lines (155 loc) · 5.44 KB
/
sale.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# -*- coding: utf-8 -*-
"""
sale.py
:copyright: (c) 2014 by Openlabs Technologies & Consulting (P) Limited
:license: BSD, see LICENSE for more details.
"""
from trytond.model import fields
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval
__all__ = ['SaleLine', 'Sale']
__metaclass__ = PoolMeta
class Sale:
"Sale"
__name__ = 'sale.sale'
is_international_shipping = fields.Function(
fields.Boolean("Is International Shipping"),
'on_change_with_is_international_shipping'
)
package_weight = fields.Function(
fields.Float(
"Package weight", digits=(16, Eval('weight_digits', 2)),
depends=['weight_digits'],
),
'get_package_weight'
)
weight_uom = fields.Function(
fields.Many2One('product.uom', 'Weight UOM'),
'get_weight_uom'
)
weight_digits = fields.Function(
fields.Integer('Weight Digits'), 'on_change_with_weight_digits'
)
@fields.depends('weight_uom')
def on_change_with_weight_digits(self, name=None):
if self.weight_uom:
return self.weight_uom.digits
return 2
def get_weight_uom(self, name):
"""
Returns weight uom for the package
"""
return self._get_weight_uom().id
def _get_weight_uom(self):
"""
Returns Pound as default value for uom
Downstream module can override this method to change weight uom as per
carrier
"""
UOM = Pool().get('product.uom')
return UOM.search([('symbol', '=', 'lb')])[0]
def get_package_weight(self, name):
"""
Returns sum of weight associated with each line
"""
weight_uom = self._get_weight_uom()
return self._get_package_weight(weight_uom)
@fields.depends('party', 'shipment_address', 'warehouse')
def on_change_with_is_international_shipping(self, name=None):
"""
Return True if international shipping
"""
from_address = self._get_ship_from_address()
if self.shipment_address and from_address and \
from_address.country and self.shipment_address.country and \
from_address.country != self.shipment_address.country:
return True
return False
def _get_package_weight(self, uom):
"""
Returns sum of weight associated with package
"""
return sum(
map(
lambda line: line.get_weight(uom, silent=True),
self.lines
)
)
def _get_ship_from_address(self):
"""
Usually the warehouse from which you ship
"""
return self.warehouse and self.warehouse.address
def add_shipping_line(self, shipment_cost, description):
"""
This method takes shipping_cost and description as arguments and writes
a shipping line. It deletes any previous shipping lines which have
a shipment_cost.
:param shipment_cost: The shipment cost calculated according to carrier
:param description: Shipping line description
"""
self.__class__.write([self], {
'lines': [
('create', [{
'type': 'line',
'product': self.carrier.carrier_product.id,
'description': description,
'quantity': 1, # XXX
'unit': self.carrier.carrier_product.sale_uom.id,
'unit_price': shipment_cost,
'shipment_cost': shipment_cost,
'amount': shipment_cost,
'taxes': [],
'sequence': 9999, # XXX
}]),
('delete', [
line for line in self.lines if line.shipment_cost
]),
]
})
class SaleLine:
'Sale Line'
__name__ = 'sale.line'
@classmethod
def __setup__(cls):
super(SaleLine, cls).__setup__()
cls._error_messages.update({
'weight_required': 'Weight is missing on the product %s',
})
def get_weight(self, weight_uom, silent=False):
"""
Returns weight as required for carriers
:param weight_uom: Weight uom used by carriers
:param silent: Raise error if not silent
"""
ProductUom = Pool().get('product.uom')
if not self.product or self.quantity <= 0 or \
self.product.type == 'service':
return 0
if not self.product.weight:
if silent:
return 0
self.raise_user_error(
'weight_required',
error_args=(self.product.name,)
)
# Find the quantity in the default uom of the product as the weight
# is for per unit in that uom
if self.unit != self.product.default_uom:
quantity = ProductUom.compute_qty(
self.unit,
self.quantity,
self.product.default_uom
)
else:
quantity = self.quantity
weight = self.product.weight * quantity
# Compare product weight uom with the weight uom used by carrier
# and calculate weight if botth are not same
if self.product.weight_uom.symbol != weight_uom.symbol:
weight = ProductUom.compute_qty(
self.product.weight_uom,
weight,
weight_uom,
)
return weight