mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-21 17:52:03 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
152
odoo-bringout-oca-ddmrp-ddmrp/ddmrp/models/stock_move.py
Normal file
152
odoo-bringout-oca-ddmrp-ddmrp/ddmrp/models/stock_move.py
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# Copyright 2019-20 ForgeFlow S.L. (http://www.forgeflow.com)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
buffer_ids = fields.Many2many(
|
||||
comodel_name="stock.buffer",
|
||||
string="Linked Stock Buffers",
|
||||
)
|
||||
# Add an index as '_find_buffer_link' method is using it as search criteria
|
||||
created_purchase_line_id = fields.Many2one(index=True)
|
||||
|
||||
def _prepare_procurement_values(self):
|
||||
res = super(StockMove, self)._prepare_procurement_values()
|
||||
if self.buffer_ids:
|
||||
res["buffer_ids"] = self.buffer_ids
|
||||
return res
|
||||
|
||||
def _merge_moves_fields(self):
|
||||
res = super(StockMove, self)._merge_moves_fields()
|
||||
res["buffer_ids"] = [(4, m.id) for m in self.mapped("buffer_ids")]
|
||||
return res
|
||||
|
||||
def write(self, vals):
|
||||
res = super(StockMove, self).write(vals)
|
||||
if self and self.env.company.ddmrp_auto_update_nfp:
|
||||
# Stock moves changes can be triggered by users without
|
||||
# access to write stock buffers, thus we do it with sudo.
|
||||
if "state" in vals:
|
||||
self.sudo()._update_ddmrp_nfp()
|
||||
elif "location_id" in vals or "location_dest_id" in vals:
|
||||
self.sudo().filtered(
|
||||
lambda m: m.state
|
||||
in ("confirmed", "partially_available", "assigned")
|
||||
)._update_ddmrp_nfp()
|
||||
return res
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
moves = super(StockMove, self).create(vals_list)
|
||||
# TODO should we use @api.model_create_single instead?
|
||||
moves_to_update_ids = []
|
||||
for vals, move in zip(vals_list, moves):
|
||||
if (
|
||||
"state" in vals
|
||||
and move.state not in ("draft", "cancel")
|
||||
and self.env.company.ddmrp_auto_update_nfp
|
||||
):
|
||||
moves_to_update_ids.append(move.id)
|
||||
# Stock moves state changes can be triggered by users without
|
||||
# access to write stock buffers, thus we do it with sudo.
|
||||
if moves_to_update_ids:
|
||||
self.browse(moves_to_update_ids).sudo()._update_ddmrp_nfp()
|
||||
return moves
|
||||
|
||||
def _find_buffers_to_update_nfp(self):
|
||||
# Find buffers that can be affected. `out_buffers` will see the move as
|
||||
# outgoing and `in_buffers` as incoming.
|
||||
out_buffers = in_buffers = self.env["stock.buffer"]
|
||||
for move in self:
|
||||
out_buffers |= move.mapped("product_id.buffer_ids").filtered(
|
||||
lambda buffer: (
|
||||
move.location_id.is_sublocation_of(buffer.location_id)
|
||||
and not move.location_dest_id.is_sublocation_of(buffer.location_id)
|
||||
)
|
||||
)
|
||||
in_buffers |= move.mapped("product_id.buffer_ids").filtered(
|
||||
lambda buffer: (
|
||||
not move.location_id.is_sublocation_of(buffer.location_id)
|
||||
and move.location_dest_id.is_sublocation_of(buffer.location_id)
|
||||
)
|
||||
)
|
||||
return out_buffers, in_buffers
|
||||
|
||||
def _update_ddmrp_nfp(self):
|
||||
if self.env.context.get("no_ddmrp_auto_update_nfp"):
|
||||
return True
|
||||
out_buffers, in_buffers = self._find_buffers_to_update_nfp()
|
||||
for buffer in out_buffers.with_context(no_ddmrp_history=True):
|
||||
buffer.cron_actions(only_nfp="out")
|
||||
for buffer in in_buffers.with_context(no_ddmrp_history=True):
|
||||
buffer.cron_actions(only_nfp="in")
|
||||
|
||||
def _get_all_linked_moves(self):
|
||||
"""Retrieve all linked moves both origin and destination recursively."""
|
||||
|
||||
def get_moves(move_set, attr):
|
||||
new_moves = move_set.mapped(attr)
|
||||
while new_moves:
|
||||
move_set |= new_moves
|
||||
new_moves = new_moves.mapped(attr)
|
||||
return move_set
|
||||
|
||||
all_moves = (
|
||||
self | get_moves(self, "move_orig_ids") | get_moves(self, "move_dest_ids")
|
||||
)
|
||||
return all_moves
|
||||
|
||||
def _get_source_field_candidates(self):
|
||||
"""Extend for more source field candidates."""
|
||||
return [
|
||||
"sale_line_id.order_id",
|
||||
"purchase_line_id.order_id",
|
||||
"production_id",
|
||||
"raw_material_production_id",
|
||||
"unbuild_id",
|
||||
"repair_id",
|
||||
"rma_line_id",
|
||||
"picking_id",
|
||||
]
|
||||
|
||||
def _has_nested_field(self, field):
|
||||
"""Check if an object has a nested chain of fields."""
|
||||
current_object = self
|
||||
try:
|
||||
for field in field.split("."):
|
||||
current_object = getattr(current_object, field)
|
||||
return True
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
def _get_source_record(self):
|
||||
"""Find the first source record in the field candidates linked with the moves,
|
||||
prioritizing the order of field candidates."""
|
||||
moves = self._get_all_linked_moves()
|
||||
field_candidates = self._get_source_field_candidates()
|
||||
# Iterate over the prioritized list of candidate fields
|
||||
for field in field_candidates:
|
||||
if self._has_nested_field(field):
|
||||
for move in moves:
|
||||
record = move.mapped(field)
|
||||
if record:
|
||||
return record
|
||||
return False
|
||||
|
||||
def action_open_stock_move_source(self):
|
||||
"""Open the source record of the stock move, if it exists."""
|
||||
self.ensure_one()
|
||||
record = self._get_source_record()
|
||||
if record:
|
||||
return {
|
||||
"name": getattr(record, "name", _("Stock Move Source")),
|
||||
"view_mode": "form",
|
||||
"res_model": record._name,
|
||||
"type": "ir.actions.act_window",
|
||||
"res_id": record.id,
|
||||
}
|
||||
return False
|
||||
Loading…
Add table
Add a link
Reference in a new issue