From fe20747ddcb1e137f32bb6cc5ed6033c5ce4ff89 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Tue, 6 Jun 2017 16:05:21 +0200 Subject: [PATCH] [REF] stock: adapt traceability to new implementation --- addons/stock/__manifest__.py | 1 - addons/stock/controllers/main.py | 2 +- .../data/stock_traceability_report_data.xml | 2 +- addons/stock/models/stock_traceability.py | 287 +++++++++++------- .../js/stock_traceability_report_backend.js | 4 +- .../js/stock_traceability_report_widgets.js | 6 +- .../xml/stock_traceability_report_line.xml | 13 +- .../stock/views/report_stock_traceability.xml | 18 +- .../views/stock_production_lot_views.xml | 2 +- addons/stock/views/stock_template.xml | 9 +- .../views/stock_traceability_report_views.xml | 37 --- 11 files changed, 199 insertions(+), 182 deletions(-) delete mode 100644 addons/stock/views/stock_traceability_report_views.xml diff --git a/addons/stock/__manifest__.py b/addons/stock/__manifest__.py index 2638289e67a..d4298f7880f 100644 --- a/addons/stock/__manifest__.py +++ b/addons/stock/__manifest__.py @@ -59,7 +59,6 @@ 'views/product_views.xml', 'views/stock_config_settings_views.xml', 'views/report_stock_traceability.xml', - 'views/stock_traceability_report_views.xml', 'views/stock_template.xml', 'data/default_barcode_patterns.xml', diff --git a/addons/stock/controllers/main.py b/addons/stock/controllers/main.py index c01954ce6bc..1d9041e0ed9 100644 --- a/addons/stock/controllers/main.py +++ b/addons/stock/controllers/main.py @@ -19,7 +19,7 @@ class BarcodeController(http.Controller): class StockReportController(http.Controller): - @http.route('/mrp_workorder///', type='http', auth='user') + @http.route('/stock///', type='http', auth='user') def report(self, output_format, report_name, token, report_id=False, **kw): uid = request.session.uid domain = [('create_uid', '=', uid)] diff --git a/addons/stock/data/stock_traceability_report_data.xml b/addons/stock/data/stock_traceability_report_data.xml index 8e8f495753f..52c237d822f 100644 --- a/addons/stock/data/stock_traceability_report_data.xml +++ b/addons/stock/data/stock_traceability_report_data.xml @@ -4,7 +4,7 @@ Upstream Traceability stock_report_generic - + diff --git a/addons/stock/models/stock_traceability.py b/addons/stock/models/stock_traceability.py index e71c50c7859..f627ee7aa96 100644 --- a/addons/stock/models/stock_traceability.py +++ b/addons/stock/models/stock_traceability.py @@ -19,6 +19,47 @@ def autoIncrement(): class MrpStockReport(models.TransientModel): _name = 'stock.traceability.report' + @api.model + def get_move_lines_upstream(self, move_lines): + res = self.env['stock.pack.operation'] + for move_line in move_lines: + # if MTO + if move_line.move_id.move_orig_ids: + res |= move_line.move_id.move_orig_ids.mapped('pack_operation_ids').filtered( + lambda m: m.lot_id.id == move_line.lot_id.id) + # if MTS + else: + if move_line.location_id.usage == 'internal': + res |= self.env['stock.pack.operation'].search([ + ('product_id', '=', move_line.product_id.id), + ('lot_id', '=', move_line.lot_id.id), + ('location_dest_id', '=', move_line.location_id.id), + ('id', '!=', move_line.id), + ]) + if res: + res |= self.get_move_lines_upstream(res) + return res + + @api.model + def get_move_lines_downstream(self, move_lines): + res = self.env['stock.pack.operation'] + for move_line in move_lines: + # if MTO + if move_line.move_id.move_dest_ids: + res |= move_line.move_id.move_dest_ids.mapped('pack_operation_ids').filtered( + lambda m: m.lot_id.id == move_line.lot_id.id) + # if MTS + else: + if move_line.location_dest_id.usage == 'internal': + res |= self.env['stock.pack.operation'].search([ + ('product_id', '=', move_line.product_id.id), + ('lot_id', '=', move_line.lot_id.id), + ('location_id', '=', move_line.location_dest_id.id), + ]) + if res: + res |= self.get_move_lines_downstream(res) + return res + @api.model def get_lines(self, line_id=None, **kw): context = dict(self.env.context) @@ -33,138 +74,163 @@ class MrpStockReport(models.TransientModel): model_id = kw['model_id'] stream = kw['stream'] parent_quant = kw['parent_quant'] - StockQuant = self.env['stock.quant'] - context_ids = [] + res = [] if context.get('active_id') and not context.get('model') or context.get('model') == 'stock.production.lot': - context_ids = StockQuant.search([['lot_id', '=', context.get('active_id')]]) - elif context.get('active_id') and context.get('model') == 'mrp.production': - context_ids = self.env['mrp.production'].browse(context['active_id']).move_finished_ids.mapped('quant_ids') + if stream == "downstream": + move_ids = self.env['stock.pack.operation'].search([ + ('lot_id', '=', context.get('active_id')), + ('location_id.usage', '=', 'supplier'), + ('state', '=', 'done'), + ]) + res += self._lines(line_id, model_id=model_id, model='stock.pack.operation', level=level, parent_quant=parent_quant, + stream=stream, obj_ids=move_ids) + quant_ids = self.env['stock.quant'].search([ + ('lot_id', '=', context.get('active_id')), + ('quantity', '<', 0), + ]) + res += self._lines(line_id, model_id=model_id, model='stock.quant', level=level, + parent_quant=parent_quant, stream=stream, obj_ids=quant_ids) + else: + move_ids = self.env['stock.pack.operation'].search([ + ('lot_id', '=', context.get('active_id')), + ('location_dest_id.usage', '=', 'customer'), + ('state', '=', 'done'), + ]) + res += self._lines(line_id, model_id=model_id, model='stock.pack.operation', level=level, parent_quant=parent_quant, + stream=stream, obj_ids=move_ids) + quant_ids = self.env['stock.quant'].search([ + ('lot_id', '=', context.get('active_id')), + ('quantity', '>', 0), + ]) + res += self._lines(line_id, model_id=model_id, model='stock.quant', level=level, + parent_quant=parent_quant, stream=stream, obj_ids=quant_ids) elif context.get('active_id') and context.get('model') == 'stock.picking': - context_ids = self.env['stock.picking'].browse(context['active_id']).move_lines.mapped('quant_ids') - context.update({ - 'context_ids': context_ids or context.get('model') == 'stock.quant' and self.env[context.get('model')].browse(context.get('active_id')) or [], - 'stream': stream - }) - res = self.with_context(context)._lines(line_id, model_id=model_id, model=model, level=level, parent_quant=parent_quant) + move_ids = self.env['stock.picking'].browse(context['active_id']).move_lines.mapped('pack_operation_ids').filtered(lambda m: m.lot_id and m.state == 'done') + res = self._lines(line_id, model_id=model_id, model='stock.pack.operation', level=level, parent_quant=parent_quant, stream=stream, obj_ids=move_ids) + elif context.get('active_id') and context.get('model') == 'stock.pack.operation': + move_line_ids = self.env['stock.pack.operation'].browse(context.get('active_id')) + res = self._lines(line_id, model_id=context.get('active_id'), model=context.get('model'), level=level, parent_quant=parent_quant, stream=stream, obj_ids=move_line_ids) + else: + res = self._lines(line_id, model_id=model_id, model=model, level=level, parent_quant=parent_quant, stream=stream) return res @api.model - def get_links(self, move): + def get_links(self, move_line): res_model = '' ref = '' res_id = False - if move.picking_id: + if move_line.picking_id: res_model = 'stock.picking' - res_id = move.picking_id.id - ref = move.picking_id.name - elif move.raw_material_production_id or move.production_id: - res_model = 'mrp.production' - res_id = move.raw_material_production_id.id or move.production_id.id - ref = move.raw_material_production_id.name or move.production_id.name - elif move.unbuild_id or move.consume_unbuild_id: - res_model = 'mrp.unbuild' - res_id = move.consume_unbuild_id.id or move.unbuild_id.id - ref = move.consume_unbuild_id.name or move.unbuild_id.name + res_id = move_line.picking_id.id + ref = move_line.picking_id.name + elif move_line.move_id.inventory_id: + res_model = 'stock.inventory' + res_id = move_line.move_id.inventory_id.id + ref = move_line.move_id.inventory_id.name return res_model, res_id, ref - def make_dict_move(self, level, line_id, move, stream=False, final_vals=None): - res_model, res_id, ref = self.get_links(move) - data = { + def make_dict_move(self, level, parent_id, move_line, stream=False): + res_model, res_id, ref = self.get_links(move_line) + data = [{ 'level': level, 'unfoldable': False, - 'date': move.date, - 'parent_id': line_id, - 'model_id': move.id, - 'model':'stock.move', - 'product_id': move.product_id.display_name, - 'product_qty_uom': False, - 'location_source': move.location_id.name, - 'location_destination': move.location_dest_id.name, + 'date': move_line.move_id.date, + 'parent_id': parent_id, + 'model_id': move_line.id, + 'model':'stock.pack.operation', + 'product_id': move_line.product_id.display_name, + 'product_qty_uom': str(move_line.qty_done) + ' ' + move_line.product_id.uom_id.name, + 'location_source': move_line.location_id.name, + 'location_destination': move_line.location_dest_id.name, 'reference_id': ref, 'res_id': res_id, 'stream': stream, - 'res_model': res_model} - final_vals.append(data) - return final_vals + 'res_model': res_model}] + return data - def make_dict_head(self, level, line_id, stream=False, move=False, quant=False, final_vals=None): - if move: - res_model, res_id, ref = self.get_links(move) - final_vals.append({ + def make_dict_head(self, level, parent_id, model=False, stream=False, move_line=False): + data = [] + if model == 'stock.pack.operation': + data = [{ 'level': level, 'unfoldable': True, - 'model_id': move.id, - 'parent_id': line_id, - 'model': 'stock.move', - 'parent_quant': quant.id if quant else False, - 'product_id': move.product_id.display_name, - 'product_qty_uom': False, - 'location_source': move.location_id.name, - 'location_destination': move.location_dest_id.name, - 'reference_id': ref, - 'res_id': res_id, + 'date': move_line.move_id.date, + 'model_id': move_line.id, + 'parent_id': parent_id, + 'model': model or 'stock.pack.operation', + 'product_id': move_line.product_id.display_name+' ('+move_line.lot_id.name+')', + 'product_qty_uom': str(move_line.qty_done) + ' ' + move_line.product_id.uom_id.name, + 'location_source': move_line.location_id.name, + 'location_destination': move_line.location_dest_id.name, 'stream': stream, - 'res_model': res_model}) - else: - final_vals.append({ + 'reference_id': False}] + elif model == 'stock.quant': + data = [{ 'level': level, - 'unfoldable': True if quant.history_ids else False, - 'date': quant.lot_id.name, - 'model_id': quant.id, - 'parent_id': line_id, - 'model':'stock.quant', - 'product_id': quant.product_id.display_name, - 'product_qty_uom': str(quant.qty) + ' ' + quant.product_id.uom_id.name, - 'location_source': False, - 'location_destination': False, + 'unfoldable': True, + 'date': move_line.write_date, + 'model_id': move_line.id, + 'parent_id': parent_id, + 'model': model or 'stock.quant', + 'product_id': move_line.product_id.display_name + ' (' + move_line.lot_id.name + ')', + 'product_qty_uom': str(move_line.quantity) + ' ' + move_line.product_id.uom_id.name, + 'location_source': move_line.location_id.name, 'stream': stream, - 'reference_id': False}) + 'reference_id': False}] + return data + + @api.model + def upstream_traceability(self, level, stream=False, line_id=False, model=False, model_id=False, parent_quant=False): + model_obj = self.env[model].browse(model_id) + final_vals =[] + if model == 'stock.pack.operation': + moves = self.get_move_lines_upstream(model_obj) + for move in moves.sorted(key=lambda m: m.date, reverse=True): + final_vals += self.make_dict_move(level, stream=stream, parent_id=line_id, move_line=move) + elif model == 'stock.quant': + moves = self.env['stock.pack.operation'].search([ + ('location_dest_id', '=', model_obj.location_id.id), + ('lot_id', '=', model_obj.lot_id.id), + ('date', '<=', model_obj.write_date), + ('state', '=', 'done'), + ]) + moves |= self.get_move_lines_upstream(moves) + for move in moves.sorted(key=lambda m: m.date, reverse=True): + final_vals += self.make_dict_move(level, stream=stream, parent_id=line_id, move_line=move) return final_vals @api.model - def upstream_traceability(self, level, stream=False, line_id=False, model=False, model_id=False, parent_quant=False, final_vals=None): + def downstream_traceability(self, level, stream=False, line_id=False, model=False, model_id=False, parent_quant=False): model_obj = self.env[model].browse(model_id) - if model == 'stock.quant': - for move in model_obj.history_ids.sorted(key=lambda r: r.date, reverse=True): - if move.production_id or move.unbuild_id: - final_vals = self.make_dict_head(level, stream=stream, line_id=line_id, move=move, quant=model_obj, final_vals=final_vals) - else: - final_vals = self.make_dict_move(level, stream=stream, line_id=line_id, move=move, final_vals=final_vals) - else: - if model_obj.production_id or model_obj.unbuild_id: - parent_quant = self.env['stock.quant'].browse(parent_quant) - for quant in parent_quant.consumed_quant_ids.filtered(lambda x: x.qty > 0): - final_vals = self.make_dict_head(level, line_id=line_id, stream=stream, move=False, quant=quant, final_vals=final_vals) - - @api.model - def downstream_traceability(self, level, stream=False, line_id=False, model=False, model_id=False, parent_quant=False, final_vals=None): - model_obj = self.env[model].browse(model_id) - if model == 'stock.quant': - for move in model_obj.history_ids.sorted(key=lambda r: r.date): - if move.raw_material_production_id or move.consume_unbuild_id: - final_vals = self.make_dict_head(level, stream=stream, line_id=line_id, move=move, quant=model_obj, final_vals=final_vals) - else: - final_vals = self.make_dict_move(level, stream=stream, line_id=line_id, move=move, final_vals=final_vals) - else: - if model_obj.raw_material_production_id or model_obj.consume_unbuild_id: - parent_quant = self.env['stock.quant'].browse(parent_quant) - for quant in parent_quant.produced_quant_ids.filtered(lambda x: x.qty > 0): - final_vals = self.make_dict_head(level, stream=stream, line_id=line_id, move=False, quant=quant, final_vals=final_vals) - return True - - @api.model - def _lines(self, line_id=None, model_id=False, model=False, level=0, parent_quant=False, **kw): - lines = [] - context = dict(self.env.context) final_vals = [] - if model: - if context.get('stream') == "downstream" or context.get('stream') == 'downstream': - self.downstream_traceability(level, stream='downstream', line_id=line_id, model=model, model_id=model_id, parent_quant=parent_quant, final_vals=final_vals) + if model == 'stock.pack.operation': + moves = self.get_move_lines_downstream(model_obj) + for move in moves.sorted(key=lambda r: r.date): + final_vals += self.make_dict_move(level, stream=stream, parent_id=line_id, move_line=move) + elif model == 'stock.quant': + moves = self.env['stock.pack.operation'].search([ + ('location_id', '=', model_obj.location_id.id), + ('lot_id', '=', model_obj.lot_id.id), + ('date', '>=', model_obj.write_date), + ('state', '=', 'done'), + ]) + moves |= self.get_move_lines_downstream(moves) + for move in moves.sorted(key=lambda r: r.date): + final_vals += self.make_dict_move(level, stream=stream, parent_id=line_id, move_line=move) + return final_vals + + @api.model + def _lines(self, line_id=None, model_id=False, model=False, level=0, parent_quant=False, stream=False, obj_ids=[], **kw): + lines = [] + final_vals = [] + if model and line_id: + if stream == "downstream": + final_vals += self.downstream_traceability(level, stream='downstream', line_id=line_id, model=model, model_id=model_id, parent_quant=parent_quant) else: - self.upstream_traceability(level, stream='upstream', line_id=line_id, model=model, model_id=model_id, parent_quant=parent_quant, final_vals=final_vals) + final_vals += self.upstream_traceability(level, stream='upstream', line_id=line_id, model=model, model_id=model_id, parent_quant=parent_quant) else: - for quant in context['context_ids']: - final_vals = self.make_dict_head(level, stream=context.get('stream', False), line_id=line_id, move=False, quant=quant, final_vals=final_vals) + for move_line in obj_ids: + final_vals += self.make_dict_head(level, stream=stream, parent_id=line_id, model=model or 'stock.pack.operation', move_line=move_line) for data in final_vals: lines.append({ 'id': autoIncrement(), @@ -195,15 +261,10 @@ class MrpStockReport(models.TransientModel): for line in line_data: model = self.env[line['model_name']].browse(line['model_id']) if line.get('unfoldable'): - if line['model_name'] == 'stock.quant': - final_vals = self.make_dict_head(line['level'], line_id=line['id'], move=False, quant=model, final_vals=final_vals) - else: - final_vals = self.make_dict_head(line['level'], line_id=line['id'], move=model, quant=False, final_vals=final_vals) + final_vals += self.make_dict_head(line['level'], model=line['model_name'], parent_id=line['id'], move_line=model) else: - if line['model_name'] == 'stock.move': - final_vals = self.make_dict_move(line['level'], line_id=line['id'], move=model, final_vals=final_vals) - else: - final_vals = self.make_dict_head(line['level'], line_id=line['id'], quant=model, final_vals=final_vals) + if line['model_name'] == 'stock.pack.operation': + final_vals += self.make_dict_move(line['level'], parent_id=line['id'], move_line=model) for data in final_vals: lines.append({ 'id': autoIncrement(), @@ -233,7 +294,7 @@ class MrpStockReport(models.TransientModel): } body = self.env['ir.ui.view'].render_template( - "mrp_workorder.report_stock_inventory_print", + "stock.report_stock_inventory_print", values=dict(rcontext, lines=lines, report=self, context=self), ) @@ -252,7 +313,7 @@ class MrpStockReport(models.TransientModel): rcontext = {} context = dict(self.env.context) rcontext['lines'] = self.with_context(context).get_lines() - result['html'] = self.env.ref('mrp_workorder.report_stock_inventory').render(rcontext) + result['html'] = self.env.ref('stock.report_stock_inventory').render(rcontext) return result @api.model diff --git a/addons/stock/static/src/js/stock_traceability_report_backend.js b/addons/stock/static/src/js/stock_traceability_report_backend.js index 4a47f5abef4..dfe23c9036a 100644 --- a/addons/stock/static/src/js/stock_traceability_report_backend.js +++ b/addons/stock/static/src/js/stock_traceability_report_backend.js @@ -1,11 +1,11 @@ -odoo.define('mrp_workorder.stock_report_generic', function (require) { +odoo.define('stock.stock_report_generic', function (require) { 'use strict'; var core = require('web.core'); var Widget = require('web.Widget'); var ControlPanelMixin = require('web.ControlPanelMixin'); var session = require('web.session'); -var ReportWidget = require('mrp_workorder.ReportWidget'); +var ReportWidget = require('stock.ReportWidget'); var framework = require('web.framework'); var crash_manager = require('web.crash_manager'); diff --git a/addons/stock/static/src/js/stock_traceability_report_widgets.js b/addons/stock/static/src/js/stock_traceability_report_widgets.js index 82c612e17b1..c1abff89a56 100644 --- a/addons/stock/static/src/js/stock_traceability_report_widgets.js +++ b/addons/stock/static/src/js/stock_traceability_report_widgets.js @@ -1,4 +1,4 @@ -odoo.define('mrp_workorder.ReportWidget', function (require) { +odoo.define('stock.ReportWidget', function (require) { 'use strict'; var core = require('web.core'); @@ -19,7 +19,7 @@ var ReportWidget = Widget.extend({ this._super.apply(this, arguments); }, start: function() { - QWeb.add_template("/mrp_workorder/static/src/xml/stock_traceability_report_line.xml"); + QWeb.add_template("/stock/static/src/xml/stock_traceability_report_line.xml"); return this._super.apply(this, arguments); }, boundLink: function(e) { @@ -46,7 +46,7 @@ var ReportWidget = Widget.extend({ active_id : $el.data('model_id'), active_model : $el.data('model'), ttype: stream || false, - url: '/mrp_workorder/output_format/stock/active_id' + url: '/stock/output_format/stock/active_id' }, }); }, diff --git a/addons/stock/static/src/xml/stock_traceability_report_line.xml b/addons/stock/static/src/xml/stock_traceability_report_line.xml index ad96dc654c0..e2817032822 100644 --- a/addons/stock/static/src/xml/stock_traceability_report_line.xml +++ b/addons/stock/static/src/xml/stock_traceability_report_line.xml @@ -12,8 +12,8 @@ - - + + @@ -32,7 +32,7 @@ - + @@ -42,11 +42,6 @@ - - - - - @@ -58,7 +53,7 @@ - + diff --git a/addons/stock/views/report_stock_traceability.xml b/addons/stock/views/report_stock_traceability.xml index c975c7723ee..35cef6ec41e 100644 --- a/addons/stock/views/report_stock_traceability.xml +++ b/addons/stock/views/report_stock_traceability.xml @@ -4,8 +4,8 @@