diff --git a/stock_inventory_verification_request/README.rst b/stock_inventory_verification_request/README.rst new file mode 100644 index 000000000..4e804e087 --- /dev/null +++ b/stock_inventory_verification_request/README.rst @@ -0,0 +1,72 @@ +.. 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 + +==================================== +Stock Inventory Verification Request +==================================== + +Adds the capability to request a Slot Verification when a inventory is +'Pending to Approve'. When asked from Inventory Adjustment, which have +discrepancies over the threshold for the location, a Slot Verification +Request will be created for each line that exceed the maximum discrepancy +allowed. + +The Inventory Manager can then confirm the Slot verification and start to +check the involved Inventory Lines and Moves to find out some possible mistake +or problem. + +Usage +===== + +In order to use this module act as follow: + +* From a Inventory Adjustment in state 'Pending to Approve' click in the + button 'Request Verification'. This will create all the Slot Verification + Request needed. +* Go to 'Inventory / Inventory Control / Slot Verification Request' +* Go to a Slot Verification Request 'Waiting Actions' and confirm it. +* You can now check the involved lines and moves to help you. +* Once you have found the problem and you have fixed it 'Mark as Solved' the + Verification. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/153/9.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Lois Rilo Antelo + + +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 https://odoo-community.org. diff --git a/stock_inventory_verification_request/__init__.py b/stock_inventory_verification_request/__init__.py new file mode 100644 index 000000000..08f93b3a4 --- /dev/null +++ b/stock_inventory_verification_request/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/stock_inventory_verification_request/__openerp__.py b/stock_inventory_verification_request/__openerp__.py new file mode 100644 index 000000000..72b03ce56 --- /dev/null +++ b/stock_inventory_verification_request/__openerp__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +{ + "name": "Stock Inventory Verification Request", + "summary": "Adds the capability to request a Slot Verification when " + "a inventory is Pending to Approve", + "version": "9.0.1.0.0", + "author": "Eficent, " + "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "category": "Warehouse Management", + "depends": ["stock_inventory_discrepancy", + "mail"], + "data": [ + 'views/stock_slot_verification_request_view.xml', + 'views/stock_inventory_view.xml', + 'data/slot_verification_request_sequence.xml', + 'security/ir.model.access.csv' + ], + "license": "AGPL-3", + 'installable': True, + 'application': False, +} diff --git a/stock_inventory_verification_request/data/slot_verification_request_sequence.xml b/stock_inventory_verification_request/data/slot_verification_request_sequence.xml new file mode 100644 index 000000000..ea084b35e --- /dev/null +++ b/stock_inventory_verification_request/data/slot_verification_request_sequence.xml @@ -0,0 +1,15 @@ + + + + + + + Slot Verification Request + stock.slot.verification.request + SVR/%(range_year)s/ + 5 + + + + diff --git a/stock_inventory_verification_request/models/__init__.py b/stock_inventory_verification_request/models/__init__.py new file mode 100644 index 000000000..1e646e350 --- /dev/null +++ b/stock_inventory_verification_request/models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import stock_slot_verification_request +from . import stock_inventory diff --git a/stock_inventory_verification_request/models/stock_inventory.py b/stock_inventory_verification_request/models/stock_inventory.py new file mode 100644 index 000000000..cf7f76e42 --- /dev/null +++ b/stock_inventory_verification_request/models/stock_inventory.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from openerp import _, api, fields, models + + +class StockInventory(models.Model): + _inherit = 'stock.inventory' + + requested_verification = fields.Boolean(string='Requested Verification?', + default=False, copy=False) + slot_verification_ids = fields.One2many( + comodel_name='stock.slot.verification.request', + string='Slot Verification Requests', inverse_name='inventory_id') + + @api.multi + def action_request_verification(self): + self.requested_verification = True + for line in self.line_ids: + if line.discrepancy_threshold and (line.discrepancy_percent > + line.discrepancy_threshold): + self.env['stock.slot.verification.request'].create({ + 'inventory_id': self.id, + 'inventory_line_id': line.id, + 'location_id': line.location_id.id, + 'state': 'wait', + 'product_id': line.product_id.id, + }) + + +class StockInventoryLine(models.Model): + _inherit = 'stock.inventory.line' + + # TODO: make this work + slot_verification_ids = fields.One2many( + comodel_name='stock.slot.verification.request', + inverse_name='inventory_line_id', + string='Slot Verification Request') + + @api.multi + def action_open_svr(self): + ''' + Open the corresponding Slot Verification Request directly from the + Inventory Lines. + ''' + request_svr_ids = [] + for line in self: + request_svr_ids += line.slot_verification_ids.ids + domain = [('id', 'in', request_svr_ids)] + return {'name': _('Slot Verification Request'), + 'type': 'ir.actions.act_window', + 'res_model': 'stock.slot.verification.request', + 'view_type': 'form', + 'view_mode': 'tree,form', + 'domain': domain} diff --git a/stock_inventory_verification_request/models/stock_slot_verification_request.py b/stock_inventory_verification_request/models/stock_slot_verification_request.py new file mode 100644 index 000000000..2e3b0e7bb --- /dev/null +++ b/stock_inventory_verification_request/models/stock_slot_verification_request.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from openerp import fields, models, api + + +class SlotVerificationRequest(models.Model): + _name = 'stock.slot.verification.request' + _inherit = 'mail.thread' + + @api.model + def create(self, vals): + vals['name'] = self.env['ir.sequence'].next_by_code( + 'stock.slot.verification.request') or '' + return super(SlotVerificationRequest, self).create(vals) + + @api.one + def _count_involved_moves(self): + self.involved_move_count = len(self.involved_move_ids) + + @api.one + def _count_involved_inv_lines(self): + self.involved_inv_line_count = len(self.involved_inv_line_ids) + + name = fields.Char(string='Name', readonly=True) + inventory_id = fields.Many2one(comodel_name='stock.inventory', + string='Inventory Adjustment', + readonly=True) + inventory_line_id = fields.Many2one(comodel_name='stock.inventory.line', + string='Inventory Line', + readonly=True) + location_id = fields.Many2one(comodel_name='stock.location', + string='Location', + required=True) + state = fields.Selection(selection=[ + ('wait', 'Waiting Actions'), + ('open', 'In Progress'), + ('cancelled', 'Cancelled'), + ('done', 'Solved') + ], string='Status', default='wait') + responsible_id = fields.Many2one(comodel_name='res.users', + string='Assigned to') + product_id = fields.Many2one(comodel_name='product.product', + string='Product', required=True) + notes = fields.Text('Notes') + involved_move_ids = fields.Many2many( + comodel_name='stock.move', + relation='slot_verification_move_involved_rel', + column1='slot_verification_request_id', + column2='move_id', + string='Involved Stock Moves') + involved_move_count = fields.Integer(compute=_count_involved_moves) + involved_inv_line_ids = fields.Many2many( + comodel_name='stock.inventory.line', + relation='slot_verification_inv_line_involved_rel', + column1='slot_verification_request_id', + column2='inventory_line_id', + string='Involved Inventory Lines') + involved_inv_line_count = fields.Integer(compute=_count_involved_inv_lines) + + @api.model + def _get_involved_moves_domain(self): + domain = [('product_id', '=', self.product_id.id), '|', + ('location_id', '=', self.location_id.id), + ('location_dest_id', '=', self.location_id.id)] + return domain + + @api.model + def _get_involved_lines_domain(self): + domain = [('product_id', '=', self.product_id.id), + ('location_id', '=', self.location_id.id)] + return domain + + @api.model + def _get_involved_lines_and_locations(self): + involved_moves = self.env['stock.move'].search( + self._get_involved_moves_domain()) + involved_lines = self.env['stock.inventory.line'].search( + self._get_involved_lines_domain()) + return involved_moves, involved_lines + + @api.one + def action_confirm(self): + self.state = 'open' + involved_moves, involved_lines = \ + self._get_involved_lines_and_locations() + self.involved_move_ids = involved_moves + self.involved_inv_line_ids = involved_lines + return True + + @api.one + def action_cancel(self): + self.state = 'cancelled' + return True + + @api.one + def action_solved(self): + self.state = 'done' + return True + + @api.multi + def action_view_moves(self): + action = self.env.ref('stock.action_move_form2') + result = action.read()[0] + result['context'] = {} + moves_ids = sum([svr.involved_move_ids.ids for svr in self], []) + if len(moves_ids) > 1: + result['domain'] = \ + "[('id','in',[" + ','.join(map(str, moves_ids)) + "])]" + elif len(moves_ids) == 1: + res = self.env.ref('stock.view_move_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = moves_ids and moves_ids[0] or False + return result + + @api.multi + def action_view_inv_lines(self): + action = self.env.ref( + 'stock_inventory_verification_request.action_inv_adj_line_tree') + result = action.read()[0] + result['context'] = {} + line_ids = sum([svr.involved_inv_line_ids.ids for svr in self], []) + if len(line_ids) > 1: + result['domain'] = \ + "[('id','in',[" + ','.join(map(str, line_ids)) + "])]" + elif len(line_ids) == 1: + res = self.env.ref('stock_inventory_verification_request.' + 'view_inventory_line_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = line_ids and line_ids[0] or False + return result diff --git a/stock_inventory_verification_request/security/ir.model.access.csv b/stock_inventory_verification_request/security/ir.model.access.csv new file mode 100644 index 000000000..ac8d4d7b7 --- /dev/null +++ b/stock_inventory_verification_request/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_slot_verification_request_user,stock.slot.verification.request user,model_stock_slot_verification_request,stock.group_stock_user,1,0,0,0 +access_slot_verification_request_manager,stock.slot.verification.request manager,model_stock_slot_verification_request,stock.group_stock_manager,1,1,1,1 diff --git a/stock_inventory_verification_request/static/description/icon.png b/stock_inventory_verification_request/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/stock_inventory_verification_request/static/description/icon.png differ diff --git a/stock_inventory_verification_request/views/stock_inventory_view.xml b/stock_inventory_verification_request/views/stock_inventory_view.xml new file mode 100644 index 000000000..7d3895a6f --- /dev/null +++ b/stock_inventory_verification_request/views/stock_inventory_view.xml @@ -0,0 +1,102 @@ + + + + + + + Inventory form view - SVR extension + stock.inventory + + + + + + +
+
+ + + + + + + + + + + + + + + +
+ + +
+ +
+
+ + + + +