[IMP] Add already the possibility to fill in the products you want in an inventory
In order to do that, we change the theoretical quantity into a functional stored field. Therefore the on_change changes, but the old still work. The UoM of the inventory line is also taken into account [IMP] Manual selection, no theoretical qty compute on import, comments
This commit is contained in:
parent
edaec21835
commit
84b47f62eb
|
@ -2573,7 +2573,7 @@ class stock_inventory(osv.osv):
|
|||
:rtype: list of tuple
|
||||
"""
|
||||
#default available choices
|
||||
res_filter = [('none', _('All products')), ('product', _('One product only'))]
|
||||
res_filter = [('none', _('All products')), ('partial', _('Manual Selection of Products')), ('product', _('One product only'))]
|
||||
settings_obj = self.pool.get('stock.config.settings')
|
||||
config_ids = settings_obj.search(cr, uid, [], limit=1, order='id DESC', context=context)
|
||||
#If we don't have updated config until now, all fields are by default false and so should be not dipslayed
|
||||
|
@ -2616,7 +2616,10 @@ class stock_inventory(osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Inventoried Owner', readonly=True, states={'draft': [('readonly', False)]}, help="Specify Owner to focus your inventory on a particular Owner."),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Inventoried Lot/Serial Number', readonly=True, states={'draft': [('readonly', False)]}, help="Specify Lot/Serial Number to focus your inventory on a particular Lot/Serial Number.", copy=False),
|
||||
'move_ids_exist': fields.function(_get_move_ids_exist, type='boolean', string=' Stock Move Exists?', help='technical field for attrs in view'),
|
||||
'filter': fields.selection(_get_available_filters, 'Selection Filter', required=True),
|
||||
'filter': fields.selection(_get_available_filters, 'Inventory of', required=True,
|
||||
help="If you do an entire inventory, you can choose 'All Products' and it will prefill the inventory with the current stock. If you only do some products "\
|
||||
"(e.g. Cycle Counting) you can choose 'Manual Selection of Products' and the system won't propose anything. You can also let the "\
|
||||
"system propose for a single product / lot /... "),
|
||||
'total_qty': fields.function(_get_total_qty, type="float"),
|
||||
}
|
||||
|
||||
|
@ -2728,25 +2731,11 @@ class stock_inventory(osv.osv):
|
|||
for inventory in self.browse(cr, uid, ids, context=context):
|
||||
# If there are inventory lines already (e.g. from import), respect those and set their theoretical qty
|
||||
line_ids = [line.id for line in inventory.line_ids]
|
||||
if not line_ids:
|
||||
if not line_ids and inventory.filter != 'partial':
|
||||
#compute the inventory lines and create them
|
||||
vals = self._get_inventory_lines(cr, uid, inventory, context=context)
|
||||
for product_line in vals:
|
||||
inventory_line_obj.create(cr, uid, product_line, context=context)
|
||||
else:
|
||||
# On import calculate theoretical quantity
|
||||
quant_obj = self.pool.get("stock.quant")
|
||||
for line in inventory.line_ids:
|
||||
dom = [('company_id', '=', line.company_id.id), ('location_id', 'child_of', line.location_id.id), ('lot_id', '=', line.prod_lot_id.id),
|
||||
('product_id','=', line.product_id.id), ('owner_id', '=', line.partner_id.id)]
|
||||
if line.package_id:
|
||||
dom += [('package_id', '=', line.package_id.id)]
|
||||
quants = quant_obj.search(cr, uid, dom, context=context)
|
||||
tot_qty = 0
|
||||
for quant in quant_obj.browse(cr, uid, quants, context=context):
|
||||
tot_qty += quant.qty
|
||||
inventory_line_obj.write(cr, uid, [line.id], {'theoretical_qty': tot_qty}, context=context)
|
||||
|
||||
return self.write(cr, uid, ids, {'state': 'confirm', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)})
|
||||
|
||||
def _get_inventory_lines(self, cr, uid, inventory, context=None):
|
||||
|
@ -2802,6 +2791,19 @@ class stock_inventory_line(osv.osv):
|
|||
def _get_prodlot_change(self, cr, uid, ids, context=None):
|
||||
return self.pool.get('stock.inventory.line').search(cr, uid, [('prod_lot_id', 'in', ids)], context=context)
|
||||
|
||||
def _get_theoretical_qty(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
quant_obj = self.pool["stock.quant"]
|
||||
uom_obj = self.pool["product.uom"]
|
||||
for line in self.browse(cr, uid, ids, context=context):
|
||||
quant_ids = self._get_quants(cr, uid, line, context=context)
|
||||
quants = quant_obj.browse(cr, uid, quant_ids, context=context)
|
||||
tot_qty = sum([x.qty for x in quants])
|
||||
if line.product_uom_id and line.product_id.uom_id.id != line.product_uom_id.id:
|
||||
tot_qty = uom_obj._compute_qty_obj(cr, uid, line.product_id.uom_id, tot_qty, line.product_uom_id, context=context)
|
||||
res[line.id] = tot_qty
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'inventory_id': fields.many2one('stock.inventory', 'Inventory', ondelete='cascade', select=True),
|
||||
'location_id': fields.many2one('stock.location', 'Location', required=True, select=True),
|
||||
|
@ -2812,7 +2814,8 @@ class stock_inventory_line(osv.osv):
|
|||
'company_id': fields.related('inventory_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, select=True, readonly=True),
|
||||
'prod_lot_id': fields.many2one('stock.production.lot', 'Serial Number', domain="[('product_id','=',product_id)]"),
|
||||
'state': fields.related('inventory_id', 'state', type='char', string='Status', readonly=True),
|
||||
'theoretical_qty': fields.float('Theoretical Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), readonly=True),
|
||||
'theoretical_qty': fields.function(_get_theoretical_qty, type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
store=True, readonly=True, string="Theoretical Quantity"),
|
||||
'partner_id': fields.many2one('res.partner', 'Owner'),
|
||||
'product_name': fields.related('product_id', 'name', type='char', string='Product Name', store={
|
||||
'product.product': (_get_product_name_change, ['name', 'default_code'], 20),
|
||||
|
@ -2829,9 +2832,40 @@ class stock_inventory_line(osv.osv):
|
|||
}
|
||||
|
||||
_defaults = {
|
||||
'product_qty': 1,
|
||||
'product_qty': 0,
|
||||
}
|
||||
|
||||
def _get_quants(self, cr, uid, line, context=None):
|
||||
quant_obj = self.pool["stock.quant"]
|
||||
dom = [('company_id', '=', line.company_id.id), ('location_id', 'child_of', line.location_id.id), ('lot_id', '=', line.prod_lot_id.id),
|
||||
('product_id','=', line.product_id.id), ('owner_id', '=', line.partner_id.id), ('package_id', '=', line.package_id.id)]
|
||||
quants = quant_obj.search(cr, uid, dom, context=context)
|
||||
return quants
|
||||
|
||||
def onchange_createline(self, cr, uid, ids, location_id=False, product_id=False, uom_id=False, package_id=False, prod_lot_id=False, partner_id=False, company_id=False, context=None):
|
||||
quant_obj = self.pool["stock.quant"]
|
||||
uom_obj = self.pool["product.uom"]
|
||||
res = {'value': {}}
|
||||
# If no UoM already put the default UoM of the product
|
||||
if product_id and not uom_id:
|
||||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
res['value']['product_uom_id'] = product.uom_id.id
|
||||
res['domain'] = {'product_uom_id': [('category_id','=',product.uom_id.category_id.id)]}
|
||||
uom_id = product.uom_id.id
|
||||
# Calculate theoretical quantity by searching the quants as in quants_get
|
||||
if product_id and location_id:
|
||||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
if not company_id:
|
||||
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
||||
dom = [('company_id', '=', company_id), ('location_id', 'child_of', location_id), ('lot_id', '=', prod_lot_id),
|
||||
('product_id','=', product_id), ('owner_id', '=', partner_id), ('package_id', '=', package_id)]
|
||||
quants = quant_obj.search(cr, uid, dom, context=context)
|
||||
th_qty = sum([x.qty for x in quant_obj.browse(cr, uid, quants, context=context)])
|
||||
if product_id and uom_id and product.uom_id.id != uom_id:
|
||||
th_qty = uom_obj._compute_qty(cr, uid, product.uom_id.id, th_qty, uom_id)
|
||||
res['value']['theoretical_qty'] = th_qty
|
||||
return res
|
||||
|
||||
def _resolve_inventory_line(self, cr, uid, inventory_line, context=None):
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
diff = inventory_line.theoretical_qty - inventory_line.product_qty
|
||||
|
@ -2862,26 +2896,11 @@ class stock_inventory_line(osv.osv):
|
|||
vals['product_uom_qty'] = diff
|
||||
return stock_move_obj.create(cr, uid, vals, context=context)
|
||||
|
||||
# Should be left out in next version
|
||||
def restrict_change(self, cr, uid, ids, theoretical_qty, context=None):
|
||||
if ids and theoretical_qty:
|
||||
#if the user try to modify a line prepared by openerp, reject the change and display an error message explaining how he should do
|
||||
old_value = self.browse(cr, uid, ids[0], context=context)
|
||||
return {
|
||||
'value': {
|
||||
'product_id': old_value.product_id.id,
|
||||
'product_uom_id': old_value.product_uom_id.id,
|
||||
'location_id': old_value.location_id.id,
|
||||
'prod_lot_id': old_value.prod_lot_id.id,
|
||||
'package_id': old_value.package_id.id,
|
||||
'partner_id': old_value.partner_id.id,
|
||||
},
|
||||
'warning': {
|
||||
'title': _('Error'),
|
||||
'message': _('You can only change the checked quantity of an existing inventory line. If you want modify a data, please set the checked quantity to 0 and create a new inventory line.')
|
||||
}
|
||||
}
|
||||
return {}
|
||||
|
||||
# Should be left out in next version
|
||||
def on_change_product_id(self, cr, uid, ids, product, uom, theoretical_qty, context=None):
|
||||
""" Changes UoM
|
||||
@param location_id: Location id
|
||||
|
@ -2889,8 +2908,6 @@ class stock_inventory_line(osv.osv):
|
|||
@param uom: UoM product
|
||||
@return: Dictionary of changed values
|
||||
"""
|
||||
if ids and theoretical_qty:
|
||||
return self.restrict_change(cr, uid, ids, theoretical_qty, context=context)
|
||||
if not product:
|
||||
return {'value': {'product_uom_id': False}}
|
||||
obj_product = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_inventory_filter" model="ir.ui.view">
|
||||
<record id="view_inventory_filter" model="ir.ui.view">
|
||||
<field name="name">stock.inventory.filter</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="arch" type="xml">
|
||||
|
@ -107,10 +107,10 @@
|
|||
<group>
|
||||
<field name="date"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<field name="product_id" domain="[('type','=','product')]" attrs="{'invisible': [('filter', 'not in', ('product', 'product_owner'))]}"/>
|
||||
<field name="lot_id" attrs="{'invisible': [('filter', '!=', 'lot')]}" groups="stock.group_production_lot" />
|
||||
<field name="partner_id" attrs="{'invisible': [('filter', 'not in', ('owner', 'product_owner'))]}" groups="stock.group_tracking_owner"/>
|
||||
<field name="package_id" attrs="{'invisible': [('filter', '!=', 'pack')]}" groups="stock.group_tracking_lot"/>
|
||||
<field name="product_id" domain="[('type','=','product')]" attrs="{'invisible': [('filter', 'not in', ('product', 'product_owner'))], 'required': [('filter', 'in', ('product', 'product_owner'))]}"/>
|
||||
<field name="lot_id" attrs="{'invisible': [('filter', '!=', 'lot')], 'required': [('filter', '=', 'lot')]}" groups="stock.group_production_lot" />
|
||||
<field name="partner_id" attrs="{'invisible': [('filter', 'not in', ('owner', 'product_owner'))], 'required': [('filter', 'in', ('owner', 'product_owner'))]}" groups="stock.group_tracking_owner"/>
|
||||
<field name="package_id" attrs="{'invisible': [('filter', '!=', 'pack')], 'required': [('filter', '=', 'pack')]}" groups="stock.group_tracking_lot"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook attrs="{'invisible':[('state','=','draft')]}">
|
||||
|
@ -118,12 +118,12 @@
|
|||
<button name="reset_real_qty" states="confirm" string="⇒ Set quantities to 0" type="object" class="oe_link oe_right" groups="stock.group_stock_user"/>
|
||||
<field name="line_ids" string="Inventory Details" context="{'default_location_id': location_id, 'default_product_id': product_id, 'default_prod_lot_id': lot_id, 'default_package_id': package_id, 'default_partner_id': partner_id}">
|
||||
<tree string="Inventory Details" editable="bottom" colors="blue: product_qty != theoretical_qty; red: theoretical_qty < 0">
|
||||
<field context="{'location':location_id, 'uom':product_uom_id, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(product_id,product_uom_id,theoretical_qty,context)" domain="[('type','=','product')]"/>
|
||||
<field name="product_uom_id" groups="product.group_uom" on_change="restrict_change(theoretical_qty)"/>
|
||||
<field domain="[('usage','=','internal')]" name="location_id" groups="stock.group_locations" on_change="restrict_change(theoretical_qty)"/>
|
||||
<field name="prod_lot_id" on_change="restrict_change(theoretical_qty)" domain="[('product_id', '=', product_id)]" context="{'default_product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="package_id" on_change="restrict_change(theoretical_qty)" groups="stock.group_tracking_lot"/>
|
||||
<field name="partner_id" on_change="restrict_change(theoretical_qty)" groups="stock.group_tracking_owner"/>
|
||||
<field name="product_id" domain="[('type','=','product')]" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="product_uom_id" groups="product.group_uom" string="UoM" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="location_id" domain="[('id', 'child_of', parent.location_id)]" groups="stock.group_locations" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="prod_lot_id" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" domain="[('product_id', '=', product_id)]" context="{'default_product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="package_id" domain="['|', ('location_id','=', False), ('location_id', '=', location_id)]" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" groups="stock.group_tracking_lot"/>
|
||||
<field name="partner_id" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" groups="stock.group_tracking_owner"/>
|
||||
<field name="theoretical_qty" readonly="1"/>
|
||||
<field name="product_qty" string="Real Quantity"/>
|
||||
<field name="state" invisible="True"/>
|
||||
|
|
Loading…
Reference in New Issue