mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
stock_orderpoint_generator: Migration V9
This commit is contained in:
committed by
sergiocorato
parent
08dbfaf32e
commit
44aa70cb4f
42
stock_orderpoint_generator/README.rst
Normal file
42
stock_orderpoint_generator/README.rst
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||||
|
:alt: License: AGPL-3
|
||||||
|
|
||||||
|
=====================
|
||||||
|
Order point generator
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Add a wizard to configure order points for multiple products in one go.
|
||||||
|
|
||||||
|
|
||||||
|
Bug Tracker
|
||||||
|
===========
|
||||||
|
|
||||||
|
Bugs are tracked on `GitHub Issues
|
||||||
|
<https://github.com/OCA/stock-logistics-warehouse/issues>`_. In case of trouble, please
|
||||||
|
check there if your issue has already been reported. If you spotted it first,
|
||||||
|
help us smashing it by providing a detailed and welcomed feedback.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||||
|
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||||
|
* Cyril Gaudin <cyril.gaudin@camptocamp.com>
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. image:: https://odoo-community.org/logo.png
|
||||||
|
:alt: Odoo Community Association
|
||||||
|
:target: https://odoo-community.org
|
||||||
|
|
||||||
|
This module is maintained by the OCA.
|
||||||
|
|
||||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||||
|
mission is to support the collaborative development of Odoo features and
|
||||||
|
promote its widespread use.
|
||||||
|
|
||||||
|
To contribute to this module, please visit http://odoo-community.org.
|
||||||
4
stock_orderpoint_generator/__init__.py
Normal file
4
stock_orderpoint_generator/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from . import wizard
|
||||||
20
stock_orderpoint_generator/__openerp__.py
Normal file
20
stock_orderpoint_generator/__openerp__.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# © 2012-2016 Camptocamp SA
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
{
|
||||||
|
'name': 'Order point generator',
|
||||||
|
'summary': 'Mass configuration of stock order points',
|
||||||
|
'version': '9.0.1.0.0',
|
||||||
|
'author': "Camptocamp, Odoo Community Association (OCA)",
|
||||||
|
'category': 'Warehouse',
|
||||||
|
'license': 'AGPL-3',
|
||||||
|
'website': "http://www.camptocamp.com",
|
||||||
|
'depends': ['stock'],
|
||||||
|
'data': [
|
||||||
|
"wizard/orderpoint_generator_view.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
],
|
||||||
|
'installable': True,
|
||||||
|
'auto_install': False,
|
||||||
|
}
|
||||||
3
stock_orderpoint_generator/models/__init__.py
Normal file
3
stock_orderpoint_generator/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import orderpoint_template
|
||||||
55
stock_orderpoint_generator/models/orderpoint_template.py
Normal file
55
stock_orderpoint_generator/models/orderpoint_template.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# © 2012-2016 Camptocamp SA
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
|
||||||
|
from openerp import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class OrderpointTemplate(models.Model):
|
||||||
|
""" Template for orderpoints
|
||||||
|
|
||||||
|
Here we use same model as stock.warehouse.orderpoint but set product_id
|
||||||
|
as non mandatory as we cannot remove it. This field will be ignored.
|
||||||
|
|
||||||
|
This has the advantage of ensuring that the order point
|
||||||
|
and the order point template have the same fields.
|
||||||
|
|
||||||
|
_table is redefined to separate templates from orderpoints
|
||||||
|
"""
|
||||||
|
_name = 'stock.warehouse.orderpoint.template'
|
||||||
|
|
||||||
|
_inherit = 'stock.warehouse.orderpoint'
|
||||||
|
_table = 'stock_warehouse_orderpoint_template'
|
||||||
|
|
||||||
|
name = fields.Char(copy=True)
|
||||||
|
group_id = fields.Many2one(copy=True)
|
||||||
|
|
||||||
|
product_id = fields.Many2one(required=False)
|
||||||
|
product_uom = fields.Many2one(required=False)
|
||||||
|
|
||||||
|
def _disable_old_instances(self, product_ids):
|
||||||
|
""" Clean old instance by setting those inactives
|
||||||
|
"""
|
||||||
|
orderpoints = self.env['stock.warehouse.orderpoint'].search(
|
||||||
|
[('product_id', 'in', product_ids)]
|
||||||
|
)
|
||||||
|
orderpoints.write({'active': False})
|
||||||
|
|
||||||
|
def _create_instances(self, product_ids):
|
||||||
|
""" Create instances of model using template inherited model
|
||||||
|
"""
|
||||||
|
orderpoint_model = self.env['stock.warehouse.orderpoint']
|
||||||
|
for data in self.copy_data():
|
||||||
|
for product_id in product_ids:
|
||||||
|
data['product_id'] = product_id
|
||||||
|
orderpoint_model.create(data)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def create_orderpoints(self, product_ids):
|
||||||
|
""" Create orderpoint for *product_ids* based on these templates.
|
||||||
|
|
||||||
|
:type product_ids: list of int
|
||||||
|
"""
|
||||||
|
self._disable_old_instances(product_ids)
|
||||||
|
self._create_instances(product_ids)
|
||||||
2
stock_orderpoint_generator/security/ir.model.access.csv
Normal file
2
stock_orderpoint_generator/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_stock_warehouse_orderpoint_template,stock.warehouse.manage,model_stock_warehouse_orderpoint_template,stock.group_stock_manager,1,1,1,1
|
||||||
|
5
stock_orderpoint_generator/tests/__init__.py
Normal file
5
stock_orderpoint_generator/tests/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# © 2016 Cyril Gaudin (Camptocamp)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from . import test_orderpoint_generator
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# © 2016 Cyril Gaudin (Camptocamp)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
from openerp.exceptions import UserError
|
||||||
|
from openerp.tests import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestOrderpointGenerator(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestOrderpointGenerator, self).setUp()
|
||||||
|
|
||||||
|
self.wizard_model = self.env['stock.warehouse.orderpoint.generator']
|
||||||
|
|
||||||
|
self.orderpoint_model = self.env['stock.warehouse.orderpoint']
|
||||||
|
|
||||||
|
self.orderpoint_template_model = self.env[
|
||||||
|
'stock.warehouse.orderpoint.template'
|
||||||
|
]
|
||||||
|
|
||||||
|
self.product_model = self.env['product.product']
|
||||||
|
self.p1 = self.product_model.create({'name': 'Unittest P1'})
|
||||||
|
self.p2 = self.product_model.create({'name': 'Unittest P2'})
|
||||||
|
|
||||||
|
self.assertEqual(0, self.orderpoint_model.search_count([
|
||||||
|
('name', '=', 'OP/000445')
|
||||||
|
]))
|
||||||
|
|
||||||
|
self.template = self.orderpoint_template_model.create({
|
||||||
|
'company_id': self.ref('base.main_company'),
|
||||||
|
'location_id': self.ref('stock.stock_location_stock'),
|
||||||
|
'name': 'OP/000445',
|
||||||
|
'product_max_qty': 15.0,
|
||||||
|
'product_min_qty': 5.0,
|
||||||
|
'qty_multiple': 1,
|
||||||
|
'warehouse_id': self.ref('stock.warehouse0')
|
||||||
|
})
|
||||||
|
|
||||||
|
def check_orderpoint(self):
|
||||||
|
orderpoints = self.orderpoint_model.search([
|
||||||
|
('name', '=', 'OP/000445')
|
||||||
|
], order='product_id')
|
||||||
|
|
||||||
|
self.assertEqual(2, len(orderpoints))
|
||||||
|
|
||||||
|
self.assertEqual(self.p1, orderpoints[0].product_id)
|
||||||
|
self.assertEqual(self.p2, orderpoints[1].product_id)
|
||||||
|
|
||||||
|
for orderpoint in orderpoints:
|
||||||
|
for field in ('company_id', 'location_id', 'product_max_qty',
|
||||||
|
'product_min_qty', 'qty_multiple', 'warehouse_id'):
|
||||||
|
self.assertEqual(orderpoint[field], self.template[field])
|
||||||
|
|
||||||
|
def test_product_orderpoint(self):
|
||||||
|
|
||||||
|
wizard = self.wizard_model.with_context(
|
||||||
|
active_ids=[self.p1.id, self.p2.id]
|
||||||
|
).create({
|
||||||
|
'orderpoint_template_id': [(6, 0, [self.template.id])]
|
||||||
|
})
|
||||||
|
wizard.action_configure()
|
||||||
|
|
||||||
|
self.check_orderpoint()
|
||||||
|
|
||||||
|
def test_template_orderpoint(self):
|
||||||
|
|
||||||
|
wizard = self.wizard_model.with_context(
|
||||||
|
active_model='product.template',
|
||||||
|
active_ids=[self.p1.product_tmpl_id.id, self.p2.product_tmpl_id.id]
|
||||||
|
).create({
|
||||||
|
'orderpoint_template_id': [(6, 0, [self.template.id])]
|
||||||
|
})
|
||||||
|
wizard.action_configure()
|
||||||
|
|
||||||
|
self.check_orderpoint()
|
||||||
|
|
||||||
|
def test_template_variants_orderpoint(self):
|
||||||
|
|
||||||
|
self.product_model.create({
|
||||||
|
'product_tmpl_id': self.p1.product_tmpl_id.id,
|
||||||
|
'name': 'Unittest P1 variant'
|
||||||
|
})
|
||||||
|
|
||||||
|
wizard = self.wizard_model.with_context(
|
||||||
|
active_model='product.template',
|
||||||
|
active_ids=[self.p1.product_tmpl_id.id]
|
||||||
|
).create({
|
||||||
|
'orderpoint_template_id': [(6, 0, [self.template.id])]
|
||||||
|
})
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
wizard.action_configure()
|
||||||
3
stock_orderpoint_generator/wizard/__init__.py
Normal file
3
stock_orderpoint_generator/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import orderpoint_generator
|
||||||
45
stock_orderpoint_generator/wizard/orderpoint_generator.py
Normal file
45
stock_orderpoint_generator/wizard/orderpoint_generator.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# © 2012-2016 Camptocamp SA
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
|
||||||
|
from openerp import _, api, fields, models
|
||||||
|
|
||||||
|
from openerp.exceptions import UserError
|
||||||
|
|
||||||
|
_template_register = ['orderpoint_template_id']
|
||||||
|
|
||||||
|
|
||||||
|
class OrderpointGenerator(models.TransientModel):
|
||||||
|
""" Wizard defining stock.warehouse.orderpoint configurations for selected
|
||||||
|
products. Those configs are generated using templates
|
||||||
|
"""
|
||||||
|
|
||||||
|
_name = 'stock.warehouse.orderpoint.generator'
|
||||||
|
_description = 'Orderpoint Generator'
|
||||||
|
|
||||||
|
orderpoint_template_id = fields.Many2many(
|
||||||
|
'stock.warehouse.orderpoint.template',
|
||||||
|
rel='order_point_generator_rel',
|
||||||
|
string='Stock rule template'
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_configure(self):
|
||||||
|
""" Action to retrieve wizard data and launch creation of items.
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
|
||||||
|
product_ids = self.env.context.get('active_ids')
|
||||||
|
assert product_ids and isinstance(product_ids, list)
|
||||||
|
|
||||||
|
if self.env.context.get('active_model') == 'product.template':
|
||||||
|
templates = self.env['product.template'].browse(product_ids)
|
||||||
|
product_ids = templates.mapped('product_variant_ids.id')
|
||||||
|
if len(product_ids) != len(templates):
|
||||||
|
raise UserError(_(
|
||||||
|
'Cannot apply because some of selected '
|
||||||
|
'products has multiple variants.'
|
||||||
|
))
|
||||||
|
|
||||||
|
self.orderpoint_template_id.create_orderpoints(product_ids)
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="orderpoint_generator_view" model="ir.ui.view">
|
||||||
|
<field name="name">stock.warehouse.orderpoint.generator</field>
|
||||||
|
<field name="model">stock.warehouse.orderpoint.generator</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Product warehouse config">
|
||||||
|
<label string="This wizard will apply the following orderpoint to selected product(s)"/>
|
||||||
|
<group string="Templates" colspan="4">
|
||||||
|
<field name="orderpoint_template_id" colspan="4"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="action_configure" string="Apply" type="object" class="oe_highlight"
|
||||||
|
icon="gtk-execute"/>
|
||||||
|
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<act_window name="Product warehouse config"
|
||||||
|
res_model="stock.warehouse.orderpoint.generator"
|
||||||
|
src_model="product.product"
|
||||||
|
view_mode="form"
|
||||||
|
target="new"
|
||||||
|
key2="client_action_multi"
|
||||||
|
id="act_create_product_conf"/>
|
||||||
|
|
||||||
|
<act_window name="Product warehouse config"
|
||||||
|
res_model="stock.warehouse.orderpoint.generator"
|
||||||
|
src_model="product.template"
|
||||||
|
view_mode="form"
|
||||||
|
target="new"
|
||||||
|
key2="client_action_multi"
|
||||||
|
id="act_create_product_template_conf"/>
|
||||||
|
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user