-
-
Notifications
You must be signed in to change notification settings - Fork 196
/
Copy pathstock_picking.py
116 lines (105 loc) · 4.72 KB
/
stock_picking.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
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class StockPicking(models.Model):
_inherit = "stock.picking"
# TODO: move this field to stock_release_channel so that we don't have to alter
# _field_picking_domains.
scheduled_date_prior_to_channel_end_date_search = fields.Boolean(
store=False,
search="_search_scheduled_date_prior_to_channel_end_date",
help="Technical field to search on not processed pickings where the scheduled "
"date is prior to the end date of related channel.",
)
@api.model
def fields_get(self, allfields=None, attributes=None):
# Hide scheduled_date_prior_to_channel_end_date_search from
# filterable/searchable fields
res = super().fields_get(allfields, attributes)
if res.get("scheduled_date_prior_to_channel_end_date_search"):
res["scheduled_date_prior_to_channel_end_date_search"]["searchable"] = False
return res
@api.model
def _search_scheduled_date_prior_to_channel_end_date_condition(self):
self.env["stock.release.channel"].flush_model(["process_end_date"])
self.env["stock.picking"].flush_model(["scheduled_date"])
end_date = (
"date(stock_release_channel.process_end_date "
"at time zone 'UTC' at time zone wh.tz) "
)
now = fields.Datetime.now()
cond = f"""
CASE WHEN stock_release_channel.process_end_date is not null
THEN date(stock_picking.scheduled_date at time zone 'UTC' at time zone wh.tz)
< {end_date} + interval '1 day'
ELSE date(stock_picking.scheduled_date at time zone 'UTC' at time zone wh.tz)
< date(TIMESTAMP %s at time zone wh.tz) + interval '1 day'
END
"""
return cond, [now]
@api.model
def _search_scheduled_date_prior_to_channel_end_date(self, operator, value):
"""Search on not processed pickings where the scheduled date is prior to
the end date of related channel.
As we compare dates, we convert datetimes in the timezone of the warehouse
"""
# We use a searchable field to be able to use 'inselect' operator in
# order to avoid a subquery in the search method. This is a workaround
# since the 'inselect' operator is not supported when calling search
# method but only into search method definition.
if operator not in ["=", "!="] or not isinstance(value, bool):
raise UserError(_("Operation not supported"))
self.env["stock.picking"].flush_model(
["release_channel_id", "scheduled_date", "state"]
)
self.env["stock.release.channel"].flush_model(
["process_end_date", "warehouse_id"]
)
query = """
SELECT
stock_picking.id
FROM
stock_picking
JOIN stock_release_channel
ON stock_picking.release_channel_id = stock_release_channel.id
LEFT JOIN stock_warehouse
ON stock_warehouse.id = stock_release_channel.warehouse_id
LEFT JOIN res_partner
ON stock_warehouse.partner_id = res_partner.id
, LATERAL (select COALESCE(res_partner.tz, 'UTC') as tz) wh
WHERE
stock_picking.state NOT IN ('done', 'cancel')
AND
"""
(
cond_q,
params,
) = self._search_scheduled_date_prior_to_channel_end_date_condition()
query += cond_q
if value:
operator_inselect = "inselect" if operator == "=" else "not inselect"
else:
operator_inselect = "not inselect" if operator == "=" else "inselect"
return [("id", operator_inselect, (query, params))]
def _after_release_set_expected_date(self):
enabled_update_scheduled_date = bool(
self.env["ir.config_parameter"]
.sudo()
.get_param(
"stock_release_channel_process_end_time.stock_release_use_channel_end_date"
)
)
res = super()._after_release_set_expected_date()
for rec in self:
# Check if a channel has been assigned to the picking and write
# scheduled_date if different to avoid unnecessary write
if (
rec.state not in ("done", "cancel")
and rec.release_channel_id
and rec.release_channel_id.process_end_date
and rec.scheduled_date != rec.release_channel_id.process_end_date
and enabled_update_scheduled_date
):
rec.scheduled_date = rec.release_channel_id.process_end_date
return res