Files
odoo_source/addons/stock/models/stock_traceability.py
T
Nimesh Jethva e13efbd8b4 [IMP]stock_*: Improvement in model description
Purpose of this commit is to give description more "business oriented"
because those descriptions appears in Odoo Studio which is supposed to be used by end users, not only by developers.

Related Task ID : 37311
2018-09-21 11:45:15 +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'
_description = '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 and m.state == 'done'
) - lines_seen
# if MTS
elif move_line.location_id.usage == 'internal':
lines = self.env['stock.move.line'].search([
('product_id', '=', move_line.product_id.id),
('lot_id', '=', move_line.lot_id.id),
('location_dest_id', '=', move_line.location_id.id),
('id', 'not in', lines_seen.ids),
('date', '<=', move_line.date),
('state', '=', 'done')
])
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 = self.env['stock.move.line']
move_line = self.env['stock.move.line']
if rec_id and model == 'stock.production.lot':
lines = move_line.search([
('lot_id', '=', context.get('lot_name') or rec_id),
('state', '=', 'done'),
])
elif rec_id and model == 'stock.move.line' and context.get('lot_name'):
record = self.env[model].browse(rec_id)
dummy, is_used = self._get_linked_move_lines(record)
if is_used:
lines = is_used
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.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)
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,
'location_destination': move_line.location_dest_id.name,
'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:
# Traceability in case of consumed in.
lines = self._get_move_lines(move_line)
for line in lines:
unfoldable = False
if line.consume_line_ids or ( line.lot_id and self._get_move_lines(line) and model != "stock.production.lot"):
unfoldable = True
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()