mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
# Copyright 2020 Camptocamp SA
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
from collections import defaultdict
|
|
|
|
from odoo import _, models
|
|
from odoo.tools import float_compare
|
|
|
|
from odoo.addons.queue_job.job import identity_exact
|
|
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = "stock.move"
|
|
|
|
def _action_done(self, cancel_backorder=False):
|
|
done_moves = super()._action_done(cancel_backorder=cancel_backorder)
|
|
done_moves._prepare_auto_assign(location_field="move_line_ids.location_dest_id")
|
|
return done_moves
|
|
|
|
def _action_cancel(self):
|
|
moves_with_reservation_to_cancel = self.filtered(
|
|
lambda m: m.state not in ("done", "cancel")
|
|
and float_compare(
|
|
m.reserved_availability, 0, precision_rounding=m.product_uom.rounding
|
|
)
|
|
> 0
|
|
)
|
|
res = super()._action_cancel()
|
|
moves_with_reservation_canceled = (
|
|
self.filtered(lambda m: m.state == "cancel")
|
|
& moves_with_reservation_to_cancel
|
|
)
|
|
if moves_with_reservation_canceled:
|
|
moves_with_reservation_canceled._prepare_auto_assign(
|
|
location_field="location_id"
|
|
)
|
|
return res
|
|
|
|
def _prepare_auto_assign(self, location_field):
|
|
product_locs = defaultdict(set)
|
|
for move in self:
|
|
# select internal locations where we moved goods not for the
|
|
# purpose of another move (so no further destination move)
|
|
if move.move_dest_ids:
|
|
continue
|
|
product = move.product_id
|
|
if product.type != "product":
|
|
continue
|
|
locations = move.mapped(location_field).filtered(
|
|
lambda l: l.usage == "internal"
|
|
)
|
|
product_locs[product.id].update(locations.ids)
|
|
|
|
for product_id, location_ids in product_locs.items():
|
|
if not location_ids:
|
|
continue
|
|
self._enqueue_auto_assign(
|
|
self.env["product.product"].browse(product_id),
|
|
self.env["stock.location"].browse(location_ids),
|
|
).delay()
|
|
|
|
def _enqueue_auto_assign(self, product, locations, **job_options):
|
|
"""Enqueue a job ProductProduct.moves_auto_assign()
|
|
|
|
Can be extended to pass different options to the job (priority, ...).
|
|
The usage of `.setdefault` allows to override the options set by default.
|
|
|
|
return: a `Job` instance
|
|
"""
|
|
job_options = job_options.copy()
|
|
job_options.setdefault(
|
|
"description",
|
|
_('Try reserving "{}" for quantities added in: {}').format(
|
|
product.display_name, ", ".join(locations.mapped("name"))
|
|
),
|
|
)
|
|
# do not enqueue 2 jobs for the same product and locations set
|
|
job_options.setdefault("identity_key", identity_exact)
|
|
delayable = product.delayable(**job_options)
|
|
job = delayable.moves_auto_assign(locations)
|
|
return job
|