mrp_subcontracting/models/stock_location.py

104 lines
6.0 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class StockLocation(models.Model):
_inherit = 'stock.location'
is_subcontracting_location = fields.Boolean(
"Is a Subcontracting Location?",
help="Check this box to create a new dedicated subcontracting location for this company. Note that standard subcontracting routes will be adapted so as to take these into account automatically."
)
subcontractor_ids = fields.One2many('res.partner', 'property_stock_subcontractor')
@api.constrains('is_subcontracting_location', 'usage', 'location_id')
def _check_subcontracting_location(self):
for location in self:
if location == location.company_id.subcontracting_location_id:
raise ValidationError(_("You cannot alter the company's subcontracting location"))
if location.is_subcontracting_location and (location.usage != 'internal' or location.warehouse_id):
raise ValidationError(_("In order to manage stock accurately, subcontracting locations must be type Internal, linked to the appropriate company and not specific to a warehouse."))
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
new_subcontracting_locations = res.filtered(lambda l: l.is_subcontracting_location)
new_subcontracting_locations._activate_subcontracting_location_rules()
return res
def write(self, values):
res = super().write(values)
if 'is_subcontracting_location' in values:
if values['is_subcontracting_location']:
self._activate_subcontracting_location_rules()
else:
self._archive_subcontracting_location_rules()
return res
def _check_access_putaway(self):
""" Use sudo mode for subcontractor """
if self.env.user.partner_id.is_subcontractor:
return self.sudo()
else:
return super()._check_access_putaway()
def _activate_subcontracting_location_rules(self):
""" Create or unarchive rules for the 'custom' subcontracting location(s).
The subcontracting location defined on the company is considered as the 'reference' one.
All rules defined on this 'reference' location will be replicated on 'custom' subcontracting locations.
"""
locations_per_company = {}
for location in self:
if location.is_subcontracting_location and location != location.company_id.subcontracting_location_id:
locations_per_company.setdefault(location.company_id, []).extend(location)
new_rules_vals = []
rules_to_unarchive = self.env['stock.rule']
for company, locations in locations_per_company.items():
reference_location_id = company.subcontracting_location_id
if reference_location_id:
reference_rules_from = self.env['stock.rule'].search([('location_src_id', '=', reference_location_id.id)])
reference_rules_to = self.env['stock.rule'].search([('location_dest_id', '=', reference_location_id.id)])
for location in locations:
existing_rules = {
(rule.route_id, rule.picking_type_id, rule.action, rule.location_src_id): rule
for rule in self.env['stock.rule'].with_context(active_test=False).search([('location_src_id', '=', location.id)])
}
for rule in reference_rules_from:
if (rule.route_id, rule.picking_type_id, rule.action, location) not in existing_rules:
new_rules_vals.append(rule.copy_data({
'location_src_id': location.id,
'name': rule.name.replace(reference_location_id.name, location.name)
})[0])
else:
existing_rule = existing_rules[(rule.route_id, rule.picking_type_id, rule.action, location)]
if not existing_rule.active:
rules_to_unarchive += existing_rule
existing_rules = {
(rule.route_id, rule.picking_type_id, rule.action, rule.location_dest_id): rule
for rule in self.env['stock.rule'].with_context(active_test=False).search([('location_dest_id', '=', location.id)])
}
for rule in reference_rules_to:
if (rule.route_id, rule.picking_type_id, rule.action, location) not in existing_rules:
new_rules_vals.append(rule.copy_data({
'location_dest_id': location.id,
'name': rule.name.replace(reference_location_id.name, location.name)
})[0])
else:
existing_rule = existing_rules[(rule.route_id, rule.picking_type_id, rule.action, location)]
if not existing_rule.active:
rules_to_unarchive += existing_rule
self.env['stock.rule'].create(new_rules_vals)
rules_to_unarchive.action_unarchive()
def _archive_subcontracting_location_rules(self):
""" Archive subcontracting rules for locations that are no longer 'custom' subcontracting locations."""
reference_location_ids = self.company_id.subcontracting_location_id
reference_rules = self.env['stock.rule'].search(['|', ('location_src_id', 'in', reference_location_ids.ids), ('location_dest_id', 'in', reference_location_ids.ids)])
reference_routes = reference_rules.route_id
rules_to_archive = self.env['stock.rule'].search(['&', ('route_id', 'in', reference_routes.ids), '|', ('location_src_id', 'in', self.ids), ('location_dest_id', 'in', self.ids)])
rules_to_archive.action_archive()