Files
odoo_source/addons/stock/models/stock_traceability.py
T
Arnold Moyaux 575b8f3764 [FIX] stock: Diplay return in tracability report
Since saas-11.2 stock_tracability refactoring do not use
level on moves orig/dest and filter on return is
not usefull anymore. It should display all return order
by date.

This commit remove the codition on the return inside the search
on move lines.
2018-05-28 15:46:10 +02:00

236 lines
9.8 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, _
rec = 0
def autoIncrement():
global rec
pStart = 1
pInterval = 1
if rec == 0:
rec = pStart
else:
rec += pInterval
return rec
class MrpStockReport(models.TransientModel):
_name = 'stock.traceability.report'
@api.model
def _get_move_lines(self, move_lines):
lines_seen = move_lines
lines_todo = list(move_lines)
while lines_todo:
move_line = lines_todo.pop(0)
# if MTO
if move_line.move_id.move_orig_ids:
lines = move_line.move_id.move_orig_ids.mapped('move_line_ids').filtered(
lambda m: m.lot_id == move_line.lot_id
) - lines_seen
# if MTS
elif move_line:
lines = self.env['stock.move.line'].search([
('product_id', '=', move_line.product_id.id),
('lot_id', '=', move_line.lot_id.id),
('id', 'not in', lines_seen.ids),
('date', '<', move_line.date),
])
else:
continue
lines_todo += list(lines)
lines_seen |= lines
return lines_seen - move_lines
@api.model
def get_lines(self, line_id=None, **kw):
context = dict(self.env.context)
model = kw and kw['model_name'] or context.get('model')
rec_id = kw and kw['model_id'] or context.get('active_id')
level = kw and kw['level'] or 1
lines = []
move_line = self.env['stock.move.line']
if rec_id and model in ('stock.production.lot', 'stock.move.line'):
lines = move_line.search([
('lot_id', '=', context.get('lot_name') or rec_id),
('state', '=', 'done'),
])
if model == 'stock.move.line':
for line in lines:
dummy, is_used = self._get_linked_move_lines(line)
if is_used:
move_line |= is_used
lines = move_line
elif rec_id and model in ('stock.picking', 'mrp.production'):
record = self.env[model].browse(rec_id)
if model == 'stock.picking':
lines = record.move_lines.mapped('move_line_ids').filtered(lambda m: m.lot_id and m.state == 'done')
else:
lines = record.move_finished_ids.mapped('move_line_ids').filtered(lambda m: m.lot_id and m.state == 'done')
move_line_vals = self._lines(line_id, model_id=rec_id, model=model, level=level, move_lines=lines)
final_vals = sorted(move_line_vals, key=lambda v: v['date'], reverse=True)
lines = self._final_vals_to_lines(final_vals, level)
return lines
@api.model
def _get_reference(self, move_line):
res_model = ''
ref = ''
res_id = False
if move_line.picking_id:
res_model = 'stock.picking'
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 = 'Inv. Adj.: ' + move_line.move_id.inventory_id.name
elif move_line.move_id.scrapped and move_line.move_id.scrap_ids:
res_model = 'stock.scrap'
res_id = move_line.move_id.scrap_ids[0].id
ref = move_line.move_id.scrap_ids[0].name
return res_model, res_id, ref
@api.model
def _quantity_to_str(self, from_uom, to_uom, qty):
""" workaround to apply the float rounding logic of t-esc on data prepared server side """
qty = from_uom._compute_quantity(qty, to_uom, rounding_method='HALF-UP')
return self.env['ir.qweb.field.float'].value_to_html(qty, {'decimal_precision': 'Product Unit of Measure'})
def _get_usage(self, move_line):
usage = ''
if (move_line.location_id.usage == 'internal') and (move_line.location_dest_id.usage == 'internal'):
usage = 'internal'
elif (move_line.location_id.usage != 'internal') and (move_line.location_dest_id.usage == 'internal'):
usage = 'in'
else:
usage = 'out'
return usage
def _make_dict_move(self, level, parent_id, move_line, unfoldable=False):
res_model, res_id, ref = self._get_reference(move_line)
dummy, is_used = self._get_linked_move_lines(move_line)
unfoldable = False if not move_line.lot_id else unfoldable
data = [{
'level': level,
'unfoldable': unfoldable,
'date': move_line.move_id.date,
'parent_id': parent_id,
'is_used': bool(is_used),
'usage': self._get_usage(move_line),
'model_id': move_line.id,
'model': 'stock.move.line',
'product_id': move_line.product_id.display_name,
'product_qty_uom': "%s %s" % (self._quantity_to_str(move_line.product_uom_id, move_line.product_id.uom_id, move_line.qty_done), move_line.product_id.uom_id.name),
'lot_name': move_line.lot_id.name,
'lot_id': move_line.lot_id.id,
'location_source': move_line.location_id.name if not unfoldable or level == 1 else False,
'location_destination': move_line.location_dest_id.name if not unfoldable or level == 1 else False,
'reference_id': ref,
'res_id': res_id,
'res_model': res_model}]
return data
@api.model
def _final_vals_to_lines(self, final_vals, level):
lines = []
for data in final_vals:
lines.append({
'id': autoIncrement(),
'model': data['model'],
'model_id': data['model_id'],
'parent_id': data['parent_id'],
'usage': data.get('usage', False),
'is_used': data.get('is_used', False),
'lot_name': data.get('lot_name', False),
'lot_id': data.get('lot_id', False),
'reference': data.get('reference_id', False),
'res_id': data.get('res_id', False),
'res_model': data.get('res_model', False),
'columns': [data.get('reference_id', False),
data.get('product_id', False),
data.get('date', False),
data.get('lot_name', False),
data.get('location_source', False),
data.get('location_destination', False),
data.get('product_qty_uom', 0)],
'level': level,
'unfoldable': data['unfoldable'],
})
return lines
def _get_linked_move_lines(self, move_line):
""" This method will return the consumed line or produced line for this operation."""
return False, False
@api.model
def _lines(self, line_id=None, model_id=False, model=False, level=0, move_lines=[], **kw):
final_vals = []
lines = move_lines or []
if model and line_id:
move_line = self.env[model].browse(model_id)
move_lines, is_used = self._get_linked_move_lines(move_line)
if move_lines:
lines = move_lines
else:
if is_used:
# Traceability in case of consumed in.
move_line |= self._get_move_lines(move_line)
for line in move_line:
final_vals += self._make_dict_move(level, parent_id=line_id, move_line=line)
for line in lines:
unfoldable = bool(line.produce_line_ids or line.consume_line_ids)
final_vals += self._make_dict_move(level, parent_id=line_id, move_line=line, unfoldable=unfoldable)
return final_vals
def get_pdf_lines(self, line_data=[]):
lines = []
for line in line_data:
model = self.env[line['model_name']].browse(line['model_id'])
unfoldable = False
if line.get('unfoldable'):
unfoldable = True
final_vals = self._make_dict_move(line['level'], parent_id=line['id'], move_line=model, unfoldable=unfoldable)
lines.append(self._final_vals_to_lines(final_vals, line['level'])[0])
return lines
def get_pdf(self, line_data=[]):
lines = self.with_context(print_mode=True).get_pdf_lines(line_data)
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
rcontext = {
'mode': 'print',
'base_url': base_url,
}
body = self.env['ir.ui.view'].render_template(
"stock.report_stock_inventory_print",
values=dict(rcontext, lines=lines, report=self, context=self),
)
header = self.env['ir.actions.report'].render_template("web.internal_layout", values=rcontext)
header = self.env['ir.actions.report'].render_template("web.minimal_layout", values=dict(rcontext, subst=True, body=header))
return self.env['ir.actions.report']._run_wkhtmltopdf(
[body],
header=header,
landscape=True,
specific_paperformat_args={'data-report-margin-top': 10, 'data-report-header-spacing': 10}
)
def _get_html(self):
result = {}
rcontext = {}
context = dict(self.env.context)
rcontext['lines'] = self.with_context(context).get_lines()
result['html'] = self.env.ref('stock.report_stock_inventory').render(rcontext)
return result
@api.model
def get_html(self, given_context=None):
res = self.search([('create_uid', '=', self.env.uid)], limit=1)
if not res:
return self.create({}).with_context(given_context)._get_html()
return res.with_context(given_context)._get_html()