Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] stock, mrp, repair: locations per company #28508

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions addons/mrp/models/stock_warehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ def get_rules_dict(self):

@api.model
def _get_production_location(self):
location = self.env.ref('stock.location_production', raise_if_not_found=False)
if not location:
location = self.env['stock.location'].search([('usage', '=', 'production')], limit=1)
location = self.env['stock.location'].with_context(force_company=self.company_id.id).search([('usage', '=', 'production'), ('company_id', '=', self.company_id.id)], limit=1)
if not location:
raise UserError(_('Can\'t find any production location.'))
return location
Expand Down
2 changes: 1 addition & 1 deletion addons/mrp/report/report_stock_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ def _get_rule_loc(self, rule, product_id):
"""
res = super(ReportStockRule, self)._get_rule_loc(rule, product_id)
if rule.action == 'manufacture':
res['source'] = product_id.property_stock_production or self.env.ref('stock.location_production')
res['source'] = product_id.property_stock_production
return res
6 changes: 3 additions & 3 deletions addons/repair/data/repair_demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<field name="partner_invoice_id" ref="base.res_partner_address_1"/>
<field name="location_id" ref="stock.stock_location_stock"/>
<field name="operations" model="repair.line" eval="[(5, 0, 0), (0, 0, {
'location_dest_id': obj().env.ref('stock.location_production').id,
'location_dest_id': obj().env.ref('product.product_product_11').property_stock_production.id,
'location_id': obj().env.ref('stock.stock_location_stock').id,
'name': '[M-Las] Mouse, Laser',
'product_id': obj().env.ref('product.product_product_11').id,
Expand Down Expand Up @@ -38,7 +38,7 @@
<field name="partner_invoice_id" ref="base.res_partner_address_1"/>
<field name="location_id" ref="stock.stock_location_stock"/>
<field name="operations" model="repair.line" eval="[(5, 0, 0), (0, 0, {
'location_dest_id': obj().env.ref('stock.location_production').id,
'location_dest_id': obj().env.ref('product.product_product_12').property_stock_production.id,
'location_id': obj().env.ref('stock.stock_location_stock').id,
'name': '[M-Wir] Mouse, Wireless',
'price_unit': 50.0,
Expand Down Expand Up @@ -67,7 +67,7 @@
<field name="partner_invoice_id" ref="base.res_partner_address_1"/>
<field name="location_id" ref="stock.stock_location_14"/>
<field name="operations" model="repair.line" eval="[(5, 0, 0), (0, 0, {
'location_dest_id': obj().env.ref('stock.location_production').id,
'location_dest_id': obj().env.ref('product.product_product_13').property_stock_production.id,
'location_id': obj().env.ref('stock.stock_location_stock').id,
'name': '[RAM-SR5] RAM DDR SR5',
'price_unit': 50.0,
Expand Down
4 changes: 2 additions & 2 deletions addons/repair/tests/test_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _create_simple_operation(self, repair_id=False, qty=0.0, price_unit=0.0):
'price_unit': price_unit,
'repair_id': repair_id,
'location_id': self.env.ref('stock.stock_location_stock').id,
'location_dest_id': self.env.ref('stock.location_production').id,
'location_dest_id': product_to_add.property_stock_production.id,
})

def _create_simple_fee(self, repair_id=False, qty=0.0, price_unit=0.0):
Expand Down Expand Up @@ -145,7 +145,7 @@ def test_02_repair_noneinv(self):
'Repaired product went to the wrong location')
self.assertEqual(repair.operations.move_id.location_id.id, self.env.ref('stock.stock_location_stock').id,
'Consumed product was taken in the wrong location')
self.assertEqual(repair.operations.move_id.location_dest_id.id, self.env.ref('stock.location_production').id,
self.assertEqual(repair.operations.move_id.location_dest_id.id, self.env.ref('product.product_product_5').property_stock_production.id,
'Consumed product went to the wrong location')

# I define Invoice Method 'No Invoice' option in this repair order.
Expand Down
17 changes: 0 additions & 17 deletions addons/stock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,3 @@ def pre_init_hook(cr):
('model', 'like', '%stock%'),
('module', '=', 'stock')
]).unlink()

def _create_warehouse(cr, registry):
""" This hook is used to add a warehouse on existing companies
when module stock is installed.
"""
env = api.Environment(cr, SUPERUSER_ID, {})
company_ids = env['res.company'].search([])
company_with_warehouse = env['stock.warehouse'].search([]).mapped('company_id')
company_without_warehouse = company_ids - company_with_warehouse
for company in company_without_warehouse:
company.create_transit_location()
env['stock.warehouse'].create({
'name': company.name,
'code': company.name[:5],
'company_id': company.id,
'partner_id': company.partner_id.id
})
1 change: 0 additions & 1 deletion addons/stock/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,4 @@
'application': True,
'auto_install': False,
'pre_init_hook': 'pre_init_hook',
'post_init_hook': '_create_warehouse',
}
45 changes: 14 additions & 31 deletions addons/stock/data/stock_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,13 @@
<field name="posz">1</field>
<field name="company_id"></field>
</record>
<record id="stock_location_scrapped" model="stock.location">
<field name="name">Scrapped</field>
<field name="location_id" ref="stock_location_locations_virtual"/>
<field name="scrap_location">True</field>
<field name="usage">inventory</field>
<field name="company_id"></field>
</record>

<record id="location_inventory" model="stock.location">
<field name="name">Inventory adjustment</field>
<field name="location_id" ref="stock_location_locations_virtual"/>
<field name="usage">inventory</field>
<field name="company_id"></field>
</record>
<record id="location_procurement" model="stock.location">
<field name="name">Procurements</field>
<field name="location_id" ref="stock_location_locations_virtual"/>
<field name="usage">procurement</field>
<field name="company_id"></field>
</record>
<record id="location_production" model="stock.location">
<field name="name">Production</field>
<field name="location_id" ref="stock_location_locations_virtual"/>
<field name="usage">production</field>
<field name="company_id"></field>
</record>
<record id="stock_location_suppliers" model="stock.location">
<field name="name">Vendors</field>
<field name="location_id" ref="stock_location_locations_partner"/>
Expand Down Expand Up @@ -103,16 +84,6 @@
<field name="fields_id" search="[('model','=','res.partner'),('name','=','property_stock_customer')]"/>
<field eval="'stock.location,'+str(stock_location_customers)" name="value"/>
</record>
<record forcecreate="True" id="property_stock_inventory" model="ir.property">
<field name="name">property_stock_inventory</field>
<field name="fields_id" search="[('model','=','product.template'),('name','=','property_stock_inventory')]"/>
<field eval="'stock.location,'+str(location_inventory)" name="value"/>
</record>
<record forcecreate="True" id="property_stock_production" model="ir.property">
<field name="name">property_stock_production</field>
<field name="fields_id" search="[('model','=','product.template'),('name','=','property_stock_production')]"/>
<field eval="'stock.location,'+str(location_production)" name="value"/>
</record>


<!--
Expand Down Expand Up @@ -177,8 +148,20 @@
</function>

<!-- create the transit location for each company existing -->
<function model="res.company" name="create_transit_location">
<value model="res.company" eval="obj().search([('internal_transit_location_id', '=', False)]).ids"/>
<function model="res.company" name="create_missing_transit_location">
<value model="res.company" eval="obj()"/>
</function>
<function model="res.company" name="create_missing_warehouse">
<value model="res.company" eval="obj()"/>
</function>
<function model="res.company" name="create_missing_inventory_loss_location">
<value model="res.company" eval="obj()"/>
</function>
<function model="res.company" name="create_missing_production_location">
<value model="res.company" eval="obj()"/>
</function>
<function model="res.company" name="create_missing_scrap_location">
<value model="res.company" eval="obj()"/>
</function>
</data>
</odoo>
1 change: 0 additions & 1 deletion addons/stock/data/stock_demo2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
<field name="tracking">lot</field>
<field name="uom_id" ref="uom.product_uom_kgm"/>
<field name="uom_po_id" ref="uom.product_uom_kgm"/>
<field name="property_stock_inventory" ref="stock.location_inventory"/>
<field name="image" type="base64" file="stock/static/img/cable_management.png"/>
</record>

Expand Down
109 changes: 101 additions & 8 deletions addons/stock/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,127 @@ class Company(models.Model):
'stock.location', 'Internal Transit Location', on_delete="restrict",
help="Technical field used for resupply routes between warehouses that belong to this company")

def create_transit_location(self):
def _create_transit_location(self):
'''Create a transit location with company_id being the given company_id. This is needed
in case of resuply routes between warehouses belonging to the same company, because
we don't want to create accounting entries at that time.
'''
# TDE FIXME: called in data - should be done in init ??
parent_location = self.env.ref('stock.stock_location_locations', raise_if_not_found=False)
for company in self:
location = self.env['stock.location'].create({
'name': _('%s: Transit Location') % company.name,
'usage': 'transit',
'location_id': parent_location and parent_location.id or False,
'company_id': company.id,
})
location.sudo().write({'company_id': company.id})

company.write({'internal_transit_location_id': location.id})

warehouses = self.env['stock.warehouse'].search([('partner_id', '=', company.partner_id.id)])
warehouses.mapped('partner_id').with_context(force_company=company.id).write({
company.partner_id.with_context(force_company=company.id).write({
'property_stock_customer': location.id,
'property_stock_supplier': location.id,
})

def _create_inventory_loss_location(self):
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
inventory_loss_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_inventory')])
for company in self:
inventory_loss_location = self.env['stock.location'].create({
'name': '%s: Inventory adjustment' % company.name,
'usage': 'inventory',
'location_id': parent_location.id,
'company_id': company.id,
})
self.env['ir.property'].create({
'name': 'property_stock_inventory_%s' % company.name,
'fields_id': inventory_loss_product_template_field.id,
'company_id': company.id,
'value': 'stock.location,%d' % inventory_loss_location.id,
})

def _create_production_location(self):
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
production_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_production')])
for company in self:
production_location = self.env['stock.location'].create({
'name': '%s: Production' % company.name,
'usage': 'production',
'location_id': parent_location.id,
'company_id': company.id,
})
self.env['ir.property'].create({
'name': 'property_stock_inventory_%s' % company.name,
'fields_id': production_product_template_field.id,
'company_id': company.id,
'value': 'stock.location,%d' % production_location.id,
})

def _create_scrap_location(self):
for company in self:
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
scrap_location = self.env['stock.location'].create({
'name': '%s: Scrap' % company.name,
'usage': 'inventory',
'location_id': parent_location.id,
'company_id': company.id,
'scrap_location': True,
})

@api.model
def create_missing_warehouse(self):
""" This hook is used to add a warehouse on existing companies
when module stock is installed.
"""
company_ids = self.env['res.company'].search([])
company_with_warehouse = self.env['stock.warehouse'].search([]).mapped('company_id')
company_without_warehouse = company_ids - company_with_warehouse
for company in company_without_warehouse:
self.env['stock.warehouse'].create({
'name': company.name,
'code': company.name[:5],
'company_id': company.id,
'partner_id': company.partner_id.id,
})

@api.model
def create_missing_transit_location(self):
company_without_transit = self.env['res.company'].search([('internal_transit_location_id', '=', False)])
for company in company_without_transit:
company._create_transit_location()

@api.model
def create_missing_inventory_loss_location(self):
company_ids = self.env['res.company'].search([])
inventory_loss_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_inventory')])
companies_having_property = self.env['ir.property'].search([('fields_id', '=', inventory_loss_product_template_field.id)]).mapped('company_id')
company_without_property = company_ids - companies_having_property
for company in company_without_property:
company._create_inventory_loss_location()

@api.model
def create_missing_production_location(self):
company_ids = self.env['res.company'].search([])
production_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_production')])
companies_having_property = self.env['ir.property'].search([('fields_id', '=', production_product_template_field.id)]).mapped('company_id')
company_without_property = company_ids - companies_having_property
for company in company_without_property:
company._create_production_location()

@api.model
def create_missing_scrap_location(self):
company_ids = self.env['res.company'].search([])
companies_having_scrap_loc = self.env['stock.location'].search([('scrap_location', '=', True)]).mapped('company_id')
company_without_property = company_ids - companies_having_scrap_loc
for company in company_without_property:
company._create_scrap_location()

@api.model
def create(self, vals):
company = super(Company, self).create(vals)

company.create_transit_location()
# mutli-company rules prevents creating warehouse and sub-locations
self.env['stock.warehouse'].check_access_rights('create')
company.sudo()._create_transit_location()
company.sudo()._create_inventory_loss_location()
company.sudo()._create_production_location()
company.sudo()._create_scrap_location()
self.env['stock.warehouse'].sudo().create({'name': company.name, 'code': company.name[:5], 'company_id': company.id, 'partner_id': company.partner_id.id})
return company
6 changes: 3 additions & 3 deletions addons/stock/tests/test_warehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def test_inventory_product(self):
self.assertIn(inventory.name, inventory.move_ids.name)
self.assertEqual(inventory.move_ids.product_qty, 15.0)
self.assertEqual(inventory.move_ids.location_id, self.warehouse_1.lot_stock_id)
self.assertEqual(inventory.move_ids.location_dest_id, self.env.ref('stock.location_inventory')) # Inventory loss
self.assertEqual(inventory.move_ids.location_dest_id, self.product_1.property_stock_inventory) # Inventory loss
self.assertEqual(inventory.move_ids.state, 'done')
quants = self.env['stock.quant']._gather(self.product_1, self.env.ref('stock.location_inventory'))
quants = self.env['stock.quant']._gather(self.product_1, self.product_1.property_stock_inventory)
self.assertEqual(len(quants), 1) # One quant created for inventory loss

# Check quantity of product in various locations: current, its parent, brother and other
Expand Down Expand Up @@ -176,7 +176,7 @@ def test_inventory_adjustment_and_negative_quants_2(self):
productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
stock_location = self.env.ref('stock.stock_location_stock')
customer_location = self.env.ref('stock.stock_location_customers')
location_loss = self.env.ref('stock.location_inventory')
location_loss = productA.property_stock_inventory

# Create a picking out and force availability
picking_out = self.env['stock.picking'].create({
Expand Down