168 lines
7.9 KiB
Python
168 lines
7.9 KiB
Python
from odoo import models, fields, api
|
|
|
|
|
|
class StockQuant(models.Model):
|
|
_inherit = 'stock.quant'
|
|
|
|
dummy_id = fields.Char(compute='_compute_dummy_id', inverse='_inverse_dummy_id')
|
|
image_1920 = fields.Image(related="product_id.image_1920")
|
|
product_reference_code = fields.Char(related="product_id.code", string="Product Reference Code")
|
|
|
|
def _compute_dummy_id(self):
|
|
self.dummy_id = ''
|
|
|
|
def _inverse_dummy_id(self):
|
|
pass
|
|
|
|
@api.depends_context('barcode_view')
|
|
def _compute_display_name(self):
|
|
if not self.env.context.get('barcode_view'):
|
|
return super()._compute_display_name()
|
|
self.display_name = "Inventory Count"
|
|
|
|
@api.model
|
|
def barcode_write(self, vals):
|
|
""" Specially made to handle barcode app saving. Avoids overriding write method because pickings in barcode
|
|
will also write to quants and handling context in this case is non-trivial. This method is expected to be
|
|
called only when no record and vals is a list of lists of the form: [[1, quant_id, {write_values}],
|
|
[0, 0, {write_values}], ...]} where [1, quant_id...] updates an existing quant or {[0, 0, ...]}
|
|
when creating a new quant."""
|
|
Quant = self.env['stock.quant'].with_context(inventory_mode=True)
|
|
|
|
# TODO batch
|
|
|
|
for val in vals:
|
|
if val[0] in (0, 1) and not val[2].get('lot_id') and val[2].get('lot_name'):
|
|
quant_db = val[0] == 1 and Quant.browse(val[1]) or False
|
|
val[2]['lot_id'] = self.env['stock.lot'].create({
|
|
'name': val[2].pop('lot_name'),
|
|
'product_id': val[2].get('product_id', quant_db and quant_db.product_id.id or False),
|
|
}).id
|
|
|
|
quant_ids = []
|
|
for val in vals:
|
|
if val[0] == 1:
|
|
quant_id = val[1]
|
|
Quant.browse(quant_id).write(val[2])
|
|
quant_ids.append(quant_id)
|
|
elif val[0] == 0:
|
|
quant = Quant.create(val[2])
|
|
# in case an existing quant is written on instead (happens when scanning a product
|
|
# with quants, but not assigned to user or doesn't have an inventory date to normally show up in view)
|
|
if val[2].get('dummy_id'):
|
|
quant.write({'dummy_id': val[2].get('dummy_id')})
|
|
quant.write({'inventory_date': val[2].get('inventory_date')})
|
|
user_id = val[2].get('user_id')
|
|
# assign a user if one isn't assigned to avoid line disappearing when page left and returned to
|
|
if not quant.user_id and user_id:
|
|
quant.write({'user_id': user_id})
|
|
quant_ids.append(quant.id)
|
|
return self.browse(quant_ids)._get_stock_barcode_data()
|
|
|
|
def action_validate(self):
|
|
quants = self.with_context(inventory_mode=True).filtered(lambda q: q.inventory_quantity_set)
|
|
quants._compute_inventory_diff_quantity()
|
|
res = quants.action_apply_inventory()
|
|
if res:
|
|
return res
|
|
return True
|
|
|
|
def action_client_action(self):
|
|
""" Open the mobile view specialized in handling barcodes on mobile devices.
|
|
"""
|
|
action = self.env['ir.actions.actions']._for_xml_id('stock_barcode.stock_barcode_inventory_client_action')
|
|
return action
|
|
|
|
def _get_stock_barcode_data(self):
|
|
locations = self.env['stock.location']
|
|
company_id = self.env.company.id
|
|
package_types = self.env['stock.package.type']
|
|
valid_quants = self
|
|
if not self: # `self` is an empty recordset when we open the inventory adjustment.
|
|
warehouse_location = self.env['stock.warehouse'].search([('company_id', '=', company_id)], limit=1).lot_stock_id
|
|
quant_locations = self.env['stock.location']
|
|
if self.env.user.has_group('stock.group_stock_multi_locations'):
|
|
quant_locations = self.env['stock.location'].search([
|
|
('usage', 'in', ['internal', 'transit']),
|
|
('company_id', '=', company_id),
|
|
], order='id')
|
|
else:
|
|
quant_locations = warehouse_location
|
|
valid_quants = self.env['stock.quant'].search([
|
|
'|',
|
|
('user_id', '=?', self.env.user.id),
|
|
('user_id', '=', False),
|
|
('location_id', 'in', quant_locations.ids),
|
|
('inventory_date', '<=', fields.Date.today()),
|
|
])
|
|
locations = warehouse_location.child_internal_location_ids | valid_quants.location_id
|
|
if self.env.user.has_group('stock.group_tracking_lot'):
|
|
package_types = package_types.search([])
|
|
|
|
data = valid_quants.with_context(display_default_code=False, barcode_view=True).get_stock_barcode_data_records()
|
|
if locations:
|
|
data["records"]["stock.location"] = locations.read(locations._get_fields_stock_barcode(), load=False)
|
|
if package_types:
|
|
data["records"]["stock.package.type"] = package_types.read(package_types._get_fields_stock_barcode(), load=False)
|
|
data['line_view_id'] = self.env.ref('stock_barcode.stock_quant_barcode').id
|
|
return data
|
|
|
|
def get_stock_barcode_data_records(self):
|
|
products = self.product_id
|
|
companies = self.company_id or self.env.company
|
|
lots = self.lot_id
|
|
owners = self.owner_id
|
|
packages = self.package_id
|
|
packages |= packages.parent_package_id
|
|
uoms = products.uom_id | products.uom_ids
|
|
# If UoM setting is active, fetch all UoM's data.
|
|
if self.env.user.has_group('uom.group_uom'):
|
|
uoms = self.env['uom.uom'].with_context(active_test=False).search([])
|
|
|
|
data = {
|
|
"records": {
|
|
"stock.quant": self.read(self._get_fields_stock_barcode(), load=False),
|
|
"product.product": products.read(products._get_fields_stock_barcode(), load=False),
|
|
"stock.package": packages.read(packages._get_fields_stock_barcode(), load=False),
|
|
"res.company": companies.read(['name']),
|
|
"res.partner": owners.read(owners._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],
|
|
"show_quantity_count": self.env['ir.config_parameter'].sudo().get_param('stock.show_expected_quantity_count', default='False') == 'True',
|
|
"user_id": self.env.user.id,
|
|
}
|
|
return data
|
|
|
|
def _get_fields_stock_barcode(self):
|
|
return [
|
|
'product_id',
|
|
'location_id',
|
|
'inventory_date',
|
|
'inventory_quantity',
|
|
'inventory_quantity_set',
|
|
'quantity',
|
|
'available_quantity',
|
|
'product_uom_id',
|
|
'lot_id',
|
|
'package_id',
|
|
'owner_id',
|
|
'inventory_diff_quantity',
|
|
'dummy_id',
|
|
'user_id',
|
|
]
|
|
|
|
def _get_inventory_fields_write(self):
|
|
return ['dummy_id'] + super()._get_inventory_fields_write()
|
|
|
|
def _get_stock_barcode_specific_data(self):
|
|
return {
|
|
'product.product': self.product_id.read(self.env['product.product']._get_fields_stock_barcode(), load=False),
|
|
'uom.uom': self.product_id.uom_id.read(self.env['uom.uom']._get_fields_stock_barcode(), load=False),
|
|
'stock.location': self.location_id.read(self.env['stock.location']._get_fields_stock_barcode(), load=False),
|
|
'stock.lot': self.lot_id.read(self.env['stock.lot']._get_fields_stock_barcode(), load=False),
|
|
'stock.package': self.package_id.read(self.env['stock.package']._get_fields_stock_barcode(), load=False),
|
|
'res.partner': self.owner_id.read(self.env['res.partner']._get_fields_stock_barcode(), load=False),
|
|
}
|