forked from Mapan/odoo17e
196 lines
9.3 KiB
Python
196 lines
9.3 KiB
Python
from odoo import api, fields, models, _
|
|
|
|
|
|
class ManufacturingOrder(models.Model):
|
|
_inherit = 'mrp.production'
|
|
|
|
move_raw_line_ids = fields.One2many('stock.move.line', compute='_compute_move_raw_line_ids')
|
|
move_byproduct_line_ids = fields.One2many('stock.move.line', compute='_compute_move_byproduct_line_ids')
|
|
is_completed = fields.Boolean(compute='_compute_is_completed')
|
|
backorder_ids = fields.One2many(related='procurement_group_id.mrp_production_ids')
|
|
|
|
@api.depends('move_raw_ids')
|
|
def _compute_move_raw_line_ids(self):
|
|
for order in self:
|
|
order.move_raw_line_ids = order.move_raw_ids.move_line_ids
|
|
|
|
@api.depends('move_byproduct_ids')
|
|
def _compute_move_byproduct_line_ids(self):
|
|
for order in self:
|
|
order.move_byproduct_line_ids = order.move_byproduct_ids.move_line_ids
|
|
|
|
@api.depends('qty_produced', 'product_qty')
|
|
def _compute_is_completed(self):
|
|
for order in self:
|
|
order.is_completed = order.qty_produced == order.product_qty
|
|
|
|
def action_open_barcode_client_action(self):
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.actions"]._for_xml_id("stock_barcode_mrp.stock_barcode_mo_client_action")
|
|
action = dict(action, target='fullscreen')
|
|
action['context'] = {'active_id': self.id}
|
|
return action
|
|
|
|
def set_lot_producing(self):
|
|
""" Special mo barcode action to produce and return SN/lot data compatible with barcode app.
|
|
Helps avoid doing extra db calls within barcode that using action_generate_serial
|
|
would require."""
|
|
self._set_lot_producing()
|
|
action = False
|
|
if self.picking_type_id.auto_print_generated_mrp_lot:
|
|
action = self._autoprint_generated_lot(self.lot_producing_id)
|
|
return self.lot_producing_id.read(self.lot_producing_id._get_fields_stock_barcode(), load=False), action
|
|
|
|
def _get_fields_stock_barcode(self):
|
|
return [
|
|
'move_raw_line_ids',
|
|
'move_raw_ids',
|
|
'move_byproduct_line_ids',
|
|
'move_byproduct_ids',
|
|
'production_location_id',
|
|
'picking_type_id',
|
|
'location_src_id',
|
|
'location_dest_id',
|
|
'product_id',
|
|
'product_uom_id',
|
|
'product_qty',
|
|
'qty_producing',
|
|
'lot_producing_id',
|
|
'name',
|
|
'state',
|
|
'picking_type_id',
|
|
'company_id',
|
|
'user_id',
|
|
'procurement_group_id',
|
|
'backorder_ids',
|
|
]
|
|
|
|
def _get_stock_barcode_data(self):
|
|
# Avoid to get the products full name because code and name are separate in the barcode app.
|
|
self = self.with_context(display_default_code=False)
|
|
move_lines = self.move_raw_line_ids | self.move_byproduct_line_ids
|
|
lots = move_lines.lot_id | self.lot_producing_id
|
|
owners = move_lines.owner_id
|
|
# Fetch all implied products in `self`
|
|
products = self.product_id | (self.move_raw_ids + self.move_byproduct_ids).product_id
|
|
moves = self.move_raw_ids | self.move_byproduct_ids
|
|
packagings = products.packaging_ids
|
|
|
|
uoms = products.uom_id | move_lines.product_uom_id
|
|
# If UoM setting is active, fetch all UoM's data.
|
|
if self.env.user.has_group('uom.group_uom'):
|
|
uoms |= self.env['uom.uom'].search([])
|
|
|
|
# Fetch `stock.location`
|
|
source_locations = self.env['stock.location'].search([('id', 'child_of', self.location_src_id.ids)])
|
|
destination_locations = self.env['stock.location'].search([('id', 'child_of', self.location_dest_id.ids)])
|
|
locations = move_lines.location_id | move_lines.location_dest_id | source_locations | destination_locations | self.production_location_id
|
|
|
|
# Fetch `stock.quant.package` and `stock.package.type` if group_tracking_lot.
|
|
packages = self.env['stock.quant.package']
|
|
package_types = self.env['stock.package.type']
|
|
if self.env.user.has_group('stock.group_tracking_lot'):
|
|
packages |= move_lines.package_id | move_lines.result_package_id
|
|
packages |= self.env['stock.quant.package'].with_context(pack_locs=destination_locations.ids)._get_usable_packages()
|
|
package_types = package_types.search([])
|
|
|
|
data = {
|
|
"records": {
|
|
"mrp.production": self.read(self._get_fields_stock_barcode(), load=False),
|
|
"stock.picking.type": self.picking_type_id.read(self.picking_type_id._get_fields_stock_barcode(), load=False),
|
|
"stock.move": moves.read(moves._get_fields_stock_barcode(), load=False),
|
|
"stock.move.line": move_lines.read(move_lines._get_fields_stock_barcode(), load=False),
|
|
"product.product": products.read(products._get_fields_stock_barcode(), load=False),
|
|
"product.packaging": packagings.read(packagings._get_fields_stock_barcode(), load=False),
|
|
"res.partner": owners.read(owners._get_fields_stock_barcode(), load=False),
|
|
"stock.location": locations.read(locations._get_fields_stock_barcode(), load=False),
|
|
"stock.package.type": package_types.read(package_types._get_fields_stock_barcode(), False),
|
|
"stock.quant.package": packages.read(packages._get_fields_stock_barcode(), load=False),
|
|
"stock.lot": lots.read(lots._get_fields_stock_barcode(), load=False),
|
|
"uom.uom": uoms.read(uoms._get_fields_stock_barcode(), load=False),
|
|
},
|
|
"nomenclature_id": [self.env.company.nomenclature_id.id],
|
|
"source_location_ids": source_locations.ids,
|
|
"destination_locations_ids": destination_locations.ids,
|
|
}
|
|
|
|
data['config'] = self.picking_type_id._get_barcode_config() if self else {}
|
|
data['line_view_id'] = self.env.ref('stock_barcode.stock_move_line_product_selector').id
|
|
data['form_view_id'] = self.env.ref('stock_barcode_mrp.mrp_barcode_form').id
|
|
data['header_view_id'] = self.env.ref('stock_barcode_mrp.mrp_product_selector').id
|
|
data['scrap_view_id'] = self.env.ref('stock_barcode_mrp.scrap_product_selector').id
|
|
data['package_view_id'] = self.env.ref('stock_barcode.stock_quant_barcode_kanban').id
|
|
return data
|
|
|
|
@api.model
|
|
def filter_on_barcode(self, barcode):
|
|
""" Searches ready MOs for the scanned product or order.
|
|
"""
|
|
barcode_type = None
|
|
nomenclature = self.env.company.nomenclature_id
|
|
if nomenclature.is_gs1_nomenclature:
|
|
parsed_results = nomenclature.parse_barcode(barcode)
|
|
if parsed_results:
|
|
# filter with the last feasible rule
|
|
for result in parsed_results[::-1]:
|
|
if result['rule'].type in ('product', 'package'):
|
|
barcode_type = result['rule'].type
|
|
break
|
|
|
|
base_domain = [
|
|
('state', 'in', ['confirmed', 'progress']),
|
|
('reservation_state', '=', 'assigned'),
|
|
]
|
|
|
|
active_id = self.env.context.get('active_id')
|
|
additional_context = {
|
|
'search_default_filter_confirmed': 1,
|
|
'search_default_filter_ready': 1,
|
|
'search_default_filter_in_progress': 1,
|
|
'search_default_filter_to_close': 1,
|
|
'search_default_todo': 1,
|
|
'active_id': active_id,
|
|
}
|
|
picking_type = self.env['stock.picking.type'].browse(active_id)
|
|
mo_nums = 0
|
|
if barcode_type == 'product' or not barcode_type:
|
|
product = self.env['product.product'].search([('barcode', '=', barcode)], limit=1)
|
|
if product:
|
|
mo_nums = self.search_count(base_domain + [('product_id', '=', product.id)])
|
|
if mo_nums:
|
|
additional_context['search_default_product_id'] = product.id
|
|
else:
|
|
mo_nums = self.search_count(base_domain + [('move_raw_ids.product_id', '=', product.id)])
|
|
additional_context['search_default_move_raw_ids'] = barcode
|
|
if not barcode_type and not mo_nums: # Nothing found yet, try to find picking by name.
|
|
mo_nums = self.search_count(base_domain + [('name', '=', barcode)])
|
|
additional_context['search_default_name'] = barcode
|
|
|
|
if not mo_nums:
|
|
if barcode_type:
|
|
return {
|
|
'warning': {
|
|
'message': _("No Manufacturing Order ready for this %(barcode_type)s", barcode_type=barcode_type),
|
|
}
|
|
}
|
|
return {
|
|
'warning': {
|
|
'title': _('No product or order found for barcode %s', barcode),
|
|
'message': _('Scan a product to filter the orders.'),
|
|
}
|
|
}
|
|
|
|
action = picking_type._get_action('stock_barcode_mrp.mrp_action_kanban')
|
|
action['context'].update(additional_context)
|
|
return {'action': action}
|
|
|
|
@api.model
|
|
def _get_new_production_client_action(self):
|
|
action = self.env['ir.actions.actions']._for_xml_id('stock_barcode_mrp.stock_barcode_mo_client_action')
|
|
action = dict(action, target='fullscreen')
|
|
action['context'] = self.env.context
|
|
return {'action': action}
|
|
|
|
def _should_return_records(self):
|
|
return super()._should_return_records() and not self.env.context.get('barcode_trigger', False)
|