forked from OCA/stock-logistics-warehouse
/
product.py
124 lines (106 loc) · 4.41 KB
/
product.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
# Copyright 2018 Camptocamp SA
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# Copyright 2016 Eficent Business and IT Consulting Services S.L.
# (http://www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _
from odoo.addons import decimal_precision as dp
from odoo.addons.stock.models.product import OPERATORS
from odoo.tools.float_utils import float_round
from odoo.exceptions import UserError
UNIT = dp.get_precision('Product Unit of Measure')
class ProductTemplate(models.Model):
_inherit = "product.template"
qty_available_not_res = fields.Float(
string='Quantity On Hand Unreserved',
digits=UNIT,
compute='_compute_product_available_not_res',
search='_search_quantity_unreserved',
)
@api.multi
@api.depends('product_variant_ids.qty_available_not_res')
def _compute_product_available_not_res(self):
for tmpl in self:
if isinstance(tmpl.id, models.NewId):
continue
tmpl.qty_available_not_res = sum(
tmpl.mapped('product_variant_ids.qty_available_not_res')
)
@api.multi
def action_open_quants_unreserved(self):
products_ids = self.mapped('product_variant_ids').ids
quants = self.env['stock.quant'].search([
('product_id', 'in', products_ids),
])
quant_ids = quants.filtered(
lambda x: x.product_id.qty_available_not_res > 0
).ids
result = self.env.ref('stock.product_open_quants').read()[0]
result['domain'] = [('id', 'in', quant_ids)]
result['context'] = {
'search_default_locationgroup': 1,
'search_default_internal_loc': 1,
}
return result
def _search_quantity_unreserved(self, operator, value):
domain = [('qty_available_not_res', operator, value)]
product_variant_ids = self.env['product.product'].search(domain)
return [('product_variant_ids', 'in', product_variant_ids.ids)]
class ProductProduct(models.Model):
_inherit = 'product.product'
qty_available_not_res = fields.Float(
string='Qty Available Not Reserved',
digits=UNIT,
compute='_compute_qty_available_not_reserved',
search="_search_quantity_unreserved",
)
@api.multi
def _prepare_domain_available_not_reserved(self):
domain_quant = [
('product_id', 'in', self.ids),
]
domain_quant_locations = self._get_domain_locations()[0]
domain_quant.extend(domain_quant_locations)
return domain_quant
@api.multi
def _compute_product_available_not_res_dict(self):
res = {}
domain_quant = self._prepare_domain_available_not_reserved()
quants = self.env['stock.quant'].with_context(lang=False).read_group(
domain_quant,
['product_id', 'location_id', 'quantity', 'reserved_quantity'],
['product_id', 'location_id'],
lazy=False)
product_sums = {}
for quant in quants:
# create a dictionary with the total value per products
product_sums.setdefault(quant['product_id'][0], 0.)
product_sums[quant['product_id'][0]] += (
quant['quantity'] - quant['reserved_quantity']
)
for product in self.with_context(prefetch_fields=False, lang=''):
available_not_res = float_round(
product_sums.get(product.id, 0.0),
precision_rounding=product.uom_id.rounding
)
res[product.id] = {
'qty_available_not_res': available_not_res,
}
return res
@api.multi
def _compute_qty_available_not_reserved(self):
res = self._compute_product_available_not_res_dict()
for prod in self:
qty = res[prod.id]['qty_available_not_res']
prod.qty_available_not_res = qty
return res
def _search_quantity_unreserved(self, operator, value):
if operator not in OPERATORS:
raise UserError(_('Invalid domain operator %s') % operator)
if not isinstance(value, (float, int)):
raise UserError(_('Invalid domain right operand %s') % value)
ids = []
for product in self.search([]):
if OPERATORS[operator](product.qty_available_not_res, value):
ids.append(product.id)
return [('id', 'in', ids)]