_order = 'parent_left'
def name_get(self, cr, uid, ids, context=None):
- res = []
- if context is None:
- context = {}
- if not len(ids):
- return []
- reads = self.read(cr, uid, ids, ['name','location_id'], context=context)
- for record in reads:
- name = record['name']
- if context.get('full',False):
- if record['location_id']:
- name = record['location_id'][1] + ' / ' + name
- res.append((record['id'], name))
- else:
- res.append((record['id'], name))
- return res
+ # always return the full hierarchical name
+ res = self._complete_name(cr, uid, ids, 'complete_name', None, context=context)
+ return res.items()
def _complete_name(self, cr, uid, ids, name, args, context=None):
""" Forms complete name of location from parent location to child location.
@return: Dictionary of values
"""
- def _get_one_full_name(location, level=4):
- if location.location_id:
- parent_path = _get_one_full_name(location.location_id, level-1) + "/"
- else:
- parent_path = ''
- return parent_path + location.name
res = {}
for m in self.browse(cr, uid, ids, context=context):
- res[m.id] = _get_one_full_name(m)
+ names = [m.name]
+ parent = m.location_id
+ while parent:
+ names.append(parent.name)
+ parent = parent.location_id
+ res[m.id] = ' / '.join(reversed(names))
return res
\n* Production: Virtual counterpart location for production operations: this location consumes the raw material and produces finished products
""", select = True),
# temporarily removed, as it's unused: 'allocation_method': fields.selection([('fifo', 'FIFO'), ('lifo', 'LIFO'), ('nearest', 'Nearest')], 'Allocation Method', required=True),
- 'complete_name': fields.function(_complete_name, type='char', size=100, string="Location Name"),
+ 'complete_name': fields.function(_complete_name, type='char', size=256, string="Location Name", store=True),
'stock_real': fields.function(_product_value, type='float', string='Real Stock', multi="stock"),
'stock_virtual': fields.function(_product_value, type='float', string='Virtual Stock', multi="stock"),
'stock_virtual_value': fields.function(_product_value, type='float', string='Virtual Stock Value', multi="stock", digits_compute=dp.get_precision('Account')),
'company_id': fields.many2one('res.company', 'Company', select=1, help='Let this field empty if this location is shared between all companies'),
'scrap_location': fields.boolean('Scrap Location', help='Check this box to allow using this location to put scrapped/damaged goods.'),
- 'valuation_in_account_id': fields.many2one('account.account', 'Stock Input Account',domain = [('type','=','other')], help='This account will be used to value stock moves that have this location as destination, instead of the stock output account from the product.'),
- 'valuation_out_account_id': fields.many2one('account.account', 'Stock Output Account',domain = [('type','=','other')], help='This account will be used to value stock moves that have this location as source, instead of the stock input account from the product.'),
+ 'valuation_in_account_id': fields.many2one('account.account', 'Stock Valuation Account (Incoming)', domain = [('type','=','other')],
+ help="Used for real-time inventory valuation. When set on a virtual location (non internal type), "
+ "this account will be used to hold the value of products being moved from an internal location "
+ "into this location, instead of the generic Stock Output Account set on the product. "
+ "This has no effect for internal locations."),
+ 'valuation_out_account_id': fields.many2one('account.account', 'Stock Valuation Account (Outgoing)', domain = [('type','=','other')],
+ help="Used for real-time inventory valuation. When set on a virtual location (non internal type), "
+ "this account will be used to hold the value of products being moved out of this location "
+ "and into an internal location, instead of the generic Stock Output Account set on the product. "
+ "This has no effect for internal locations."),
}
_defaults = {
'active': True,
""",
(id, id, product_id))
results += cr.dictfetchall()
-
total = 0.0
results2 = 0.0
for r in results:
amount = self.pool.get('product.uom')._compute_qty(cr, uid, r['product_uom'], r['product_qty'], context.get('uom', False))
results2 += amount
total += amount
-
if total <= 0.0:
continue
@param context: A standard dictionary
@return: A dictionary of values
"""
- value={}
- value=self.pool.get('action.traceability').action_traceability(cr,uid,ids,context)
- return value
+ return self.pool.get('action.traceability').action_traceability(cr,uid,ids,context)
+
stock_tracking()
#----------------------------------------------------------
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.picking', context=c)
}
+ _sql_constraints = [
+ ('name_uniq', 'unique(name, company_id)', 'Reference must be unique per Company!'),
+ ]
+
def action_process(self, cr, uid, ids, context=None):
if context is None: context = {}
- partial_id = self.pool.get("stock.partial.picking").create(
- cr, uid, {}, context=dict(context, active_ids=ids))
+ context = dict(context, active_ids=ids, active_model=self._name)
+ partial_id = self.pool.get("stock.partial.picking").create(cr, uid, {}, context=context)
return {
'name':_("Products to Process"),
'view_mode': 'form',
'nodestroy': True,
'target': 'new',
'domain': '[]',
- 'context': dict(context, active_ids=ids)
+ 'context': context,
}
def copy(self, cr, uid, id, default=None, context=None):
default['name'] = self.pool.get('ir.sequence').get(cr, uid, seq_obj_name)
default['origin'] = ''
default['backorder_id'] = False
+ if picking_obj.invoice_state == 'invoiced':
+ default['invoice_state'] = '2binvoiced'
res=super(stock_picking, self).copy(cr, uid, id, default, context)
if res:
picking_obj = self.browse(cr, uid, res, context=context)
""" Tests whether the move is in assigned state or not.
@return: True or False
"""
+ #TOFIX: assignment of move lines should be call before testing assigment otherwise picking never gone in assign state
ok = True
for pick in self.browse(cr, uid, ids):
mt = pick.move_type
for pick in self.browse(cr, uid, ids, context=context):
todo = []
for move in pick.move_lines:
- if move.state == 'assigned':
+ if move.state == 'draft':
+ self.pool.get('stock.move').action_confirm(cr, uid, [move.id],
+ context=context)
+ todo.append(move.id)
+ elif move.state in ('assigned','confirmed'):
todo.append(move.id)
if len(todo):
self.pool.get('stock.move').action_done(cr, uid, todo,
for picking in self.browse(cr, uid, ids, context=context):
if picking.invoice_state != '2binvoiced':
continue
- payment_term_id = False
partner = picking.address_id and picking.address_id.partner_id
if not partner:
raise osv.except_osv(_('Error, no partner !'),
if inv_type in ('out_invoice', 'out_refund'):
account_id = partner.property_account_receivable.id
- payment_term_id = self._get_payment_term(cr, uid, picking)
else:
account_id = partner.property_account_payable.id
-
address_contact_id, address_invoice_id = \
self._get_address_invoice(cr, uid, picking).values()
address = address_obj.browse(cr, uid, address_contact_id, context=context)
'address_invoice_id': address_invoice_id,
'address_contact_id': address_contact_id,
'comment': comment,
- 'payment_term': payment_term_id,
+ 'payment_term': self._get_payment_term(cr, uid, picking),
'fiscal_position': partner.property_account_position.id,
'date_invoice': context.get('date_inv',False),
'company_id': picking.company_id.id,
for pick in self.browse(cr, uid, ids, context=context):
new_picking = None
complete, too_many, too_few = [], [], []
- move_product_qty = {}
- prodlot_ids = {}
- product_avail = {}
+ move_product_qty, prodlot_ids, product_avail, partial_qty, product_uoms = {}, {}, {}, {}, {}
for move in pick.move_lines:
if move.state in ('done', 'cancel'):
continue
product_currency = partial_data.get('product_currency',False)
prodlot_id = partial_data.get('prodlot_id')
prodlot_ids[move.id] = prodlot_id
- if move.product_qty == product_qty:
+ product_uoms[move.id] = product_uom
+ partial_qty[move.id] = uom_obj._compute_qty(cr, uid, product_uoms[move.id], product_qty, move.product_uom.id)
+ if move.product_qty == partial_qty[move.id]:
complete.append(move)
- elif move.product_qty > product_qty:
+ elif move.product_qty > partial_qty[move.id]:
too_few.append(move)
else:
too_many.append(move)
for move in too_few:
product_qty = move_product_qty[move.id]
-
if not new_picking:
new_picking = self.copy(cr, uid, pick.id,
{
'state': 'assigned',
'move_dest_id': False,
'price_unit': move.price_unit,
+ 'product_uom': product_uoms[move.id]
}
prodlot_id = prodlot_ids[move.id]
if prodlot_id:
defaults.update(prodlot_id=prodlot_id)
move_obj.copy(cr, uid, move.id, defaults)
-
move_obj.write(cr, uid, [move.id],
{
- 'product_qty' : move.product_qty - product_qty,
- 'product_uos_qty':move.product_qty - product_qty, #TODO: put correct uos_qty
+ 'product_qty' : move.product_qty - partial_qty[move.id],
+ 'product_uos_qty': move.product_qty - partial_qty[move.id], #TODO: put correct uos_qty
+
})
if new_picking:
move_obj.write(cr, uid, [c.id for c in complete], {'picking_id': new_picking})
for move in complete:
+ defaults = {'product_uom': product_uoms[move.id], 'product_qty': move_product_qty[move.id]}
if prodlot_ids.get(move.id):
- move_obj.write(cr, uid, [move.id], {'prodlot_id': prodlot_ids[move.id]})
+ defaults.update({'prodlot_id': prodlot_ids[move.id]})
+ move_obj.write(cr, uid, [move.id], defaults)
for move in too_many:
product_qty = move_product_qty[move.id]
defaults = {
'product_qty' : product_qty,
'product_uos_qty': product_qty, #TODO: put correct uos_qty
+ 'product_uom': product_uoms[move.id]
}
prodlot_id = prodlot_ids.get(move.id)
if prodlot_ids.get(move.id):
defaults.update(picking_id=new_picking)
move_obj.write(cr, uid, [move.id], defaults)
-
# At first we confirm the new picking (if necessary)
if new_picking:
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
name = '%s [%s]' % (name, record['ref'])
res.append((record['id'], name))
return res
+
+ def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
+ args = args or []
+ ids = []
+ if name:
+ ids = self.search(cr, uid, [('prefix', '=', name)] + args, limit=limit, context=context)
+ if not ids:
+ ids = self.search(cr, uid, [('name', operator, name)] + args, limit=limit, context=context)
+ else:
+ ids = self.search(cr, uid, args, limit=limit, context=context)
+ return self.name_get(cr, uid, ids, context)
_name = 'stock.production.lot'
_description = 'Production lot'
def action_partial_move(self, cr, uid, ids, context=None):
if context is None: context = {}
+ if context.get('active_model') != self._name:
+ context.update(active_ids=ids, active_model=self._name)
partial_id = self.pool.get("stock.partial.move").create(
cr, uid, {}, context=context)
return {
return True
_columns = {
- 'name': fields.char('Name', size=64, required=True, select=True),
+ 'name': fields.char('Name', size=250, required=True, select=True),
'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'),
'create_date': fields.datetime('Creation Date', readonly=True, select=True),
- 'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", readonly=True),
+ 'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", states={'done': [('readonly', True)]}),
'date_expected': fields.datetime('Scheduled Date', states={'done': [('readonly', True)]},required=True, select=True, help="Scheduled date for the processing of this move"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True, domain=[('type','<>','service')],states={'done': [('readonly', True)]}),
'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product UoM'), required=True,states={'done': [('readonly', True)]}),
'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True,states={'done': [('readonly', True)]}),
- 'product_uos_qty': fields.float('Quantity (UOS)', digits_compute=dp.get_precision('Product UoM')),
- 'product_uos': fields.many2one('product.uom', 'Product UOS'),
+ 'product_uos_qty': fields.float('Quantity (UOS)', digits_compute=dp.get_precision('Product UoM'), states={'done': [('readonly', True)]}),
+ 'product_uos': fields.many2one('product.uom', 'Product UOS', states={'done': [('readonly', True)]}),
'product_packaging': fields.many2one('product.packaging', 'Packaging', help="It specifies attributes of packaging like type, quantity of packaging,etc."),
'location_id': fields.many2one('stock.location', 'Source Location', required=True, select=True,states={'done': [('readonly', True)]}, help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
'location_dest_id': fields.many2one('stock.location', 'Destination Location', required=True,states={'done': [('readonly', True)]}, select=True, help="Location where the system will stock the finished products."),
- 'address_id': fields.many2one('res.partner.address', 'Destination Address', help="Optional address where goods are to be delivered, specifically used for allotment"),
+ 'address_id': fields.many2one('res.partner.address', 'Destination Address ', states={'done': [('readonly', True)]}, help="Optional address where goods are to be delivered, specifically used for allotment"),
'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', states={'done': [('readonly', True)]}, help="Production lot is used to put a serial number on the production", select=True),
'tracking_id': fields.many2one('stock.tracking', 'Pack', select=True, states={'done': [('readonly', True)]}, help="Logistical shipping unit: pallet, box, pack ..."),
# used for colors in tree views:
'scrapped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scrapped', readonly=True),
}
+ def _check_location(self, cr, uid, ids, context=None):
+ for record in self.browse(cr, uid, ids, context=context):
+ if (record.state=='done') and (record.location_dest_id.usage == 'view' or record.location_id.usage == 'view'):
+ return False
+ return True
+
_constraints = [
(_check_tracking,
'You must assign a production lot for this product',
['prodlot_id']),
+ (_check_location, 'You can not move products from or to a location of the type view.',
+ ['location_id','location_dest_id']),
(_check_product_lot,
'You try to assign a lot which is not from the same product',
['prodlot_id'])]
""" Gets default address of partner for destination location
@return: Address id or False
"""
+ mod_obj = self.pool.get('ir.model.data')
+ picking_type = context.get('picking_type')
+ location_id = False
+
if context is None:
context = {}
if context.get('move_line', []):
if context['move_line'][0]:
if isinstance(context['move_line'][0], (tuple, list)):
- return context['move_line'][0][2] and context['move_line'][0][2].get('location_dest_id',False)
+ location_id = context['move_line'][0][2] and context['move_line'][0][2].get('location_dest_id',False)
else:
move_list = self.pool.get('stock.move').read(cr, uid, context['move_line'][0], ['location_dest_id'])
- return move_list and move_list['location_dest_id'][0] or False
- if context.get('address_out_id', False):
+ location_id = move_list and move_list['location_dest_id'][0] or False
+ elif context.get('address_out_id', False):
property_out = self.pool.get('res.partner.address').browse(cr, uid, context['address_out_id'], context).partner_id.property_stock_customer
- return property_out and property_out.id or False
- return False
+ location_id = property_out and property_out.id or False
+ else:
+ location_xml_id = False
+ if picking_type == 'in':
+ location_xml_id = 'stock_location_stock'
+ elif picking_type == 'out':
+ location_xml_id = 'stock_location_customers'
+ if location_xml_id:
+ location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', location_xml_id)
+ return location_id
def _default_location_source(self, cr, uid, context=None):
""" Gets default address of partner for source location
@return: Address id or False
"""
+ mod_obj = self.pool.get('ir.model.data')
+ picking_type = context.get('picking_type')
+ location_id = False
+
if context is None:
context = {}
if context.get('move_line', []):
try:
- return context['move_line'][0][2]['location_id']
+ location_id = context['move_line'][0][2]['location_id']
except:
pass
- if context.get('address_in_id', False):
+ elif context.get('address_in_id', False):
part_obj_add = self.pool.get('res.partner.address').browse(cr, uid, context['address_in_id'], context=context)
if part_obj_add.partner_id:
- return part_obj_add.partner_id.property_stock_supplier.id
- return False
+ location_id = part_obj_add.partner_id.property_stock_supplier.id
+ else:
+ location_xml_id = False
+ if picking_type == 'in':
+ location_xml_id = 'stock_location_suppliers'
+ elif picking_type == 'out':
+ location_xml_id = 'stock_location_stock'
+ if location_xml_id:
+ location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', location_xml_id)
+ return location_id
_defaults = {
'location_id': _default_location_source,
""" On change of product id, if finds UoM, UoS, quantity and UoS quantity.
@param prod_id: Changed Product id
@param loc_id: Source location id
- @param loc_id: Destination location id
+ @param loc_dest_id: Destination location id
@param address_id: Address id of partner
@return: Dictionary of values
"""
result['location_dest_id'] = loc_dest_id
return {'value': result}
+ def onchange_date(self, cr, uid, ids, date, date_expected, context=None):
+ """ On change of Scheduled Date gives a Move date.
+ @param date_expected: Scheduled Date
+ @param date: Move Date
+ @return: Move Date
+ """
+ if not date_expected:
+ date_expected = time.strftime('%Y-%m-%d %H:%M:%S')
+ return {'value':{'date': date_expected}}
+
def _chain_compute(self, cr, uid, moves, context=None):
""" Finds whether the location has chained location type or not.
@param moves: Stock moves
result[m.picking_id].append( (m, dest) )
return result
- def _create_chained_picking(self, cr, uid, pick_name, picking, ptype, move, context=None):
- res_obj = self.pool.get('res.company')
+ def _prepare_chained_picking(self, cr, uid, picking_name, picking, picking_type, moves_todo, context=None):
+ """Prepare the definition (values) to create a new chained picking.
+
+ :param str picking_name: desired new picking name
+ :param browse_record picking: source picking (being chained to)
+ :param str picking_type: desired new picking type
+ :param list moves_todo: specification of the stock moves to be later included in this
+ picking, in the form::
+
+ [[move, (dest_location, auto_packing, chained_delay, chained_journal,
+ chained_company_id, chained_picking_type)],
+ ...
+ ]
+
+ See also :meth:`stock_location.chained_location_get`.
+ """
+ res_company = self.pool.get('res.company')
+ return {
+ 'name': picking_name,
+ 'origin': tools.ustr(picking.origin or ''),
+ 'type': picking_type,
+ 'note': picking.note,
+ 'move_type': picking.move_type,
+ 'auto_picking': moves_todo[0][1][1] == 'auto',
+ 'stock_journal_id': moves_todo[0][1][3],
+ 'company_id': moves_todo[0][1][4] or res_company._company_default_get(cr, uid, 'stock.company', context=context),
+ 'address_id': picking.address_id.id,
+ 'invoice_state': 'none',
+ 'date': picking.date,
+ }
+
+ def _create_chained_picking(self, cr, uid, picking_name, picking, picking_type, moves_todo, context=None):
picking_obj = self.pool.get('stock.picking')
- pick_id= picking_obj.create(cr, uid, {
- 'name': pick_name,
- 'origin': tools.ustr(picking.origin or ''),
- 'type': ptype,
- 'note': picking.note,
- 'move_type': picking.move_type,
- 'auto_picking': move[0][1][1] == 'auto',
- 'stock_journal_id': move[0][1][3],
- 'company_id': move[0][1][4] or res_obj._company_default_get(cr, uid, 'stock.company', context=context),
- 'address_id': picking.address_id.id,
- 'invoice_state': 'none',
- 'date': picking.date,
- })
- return pick_id
+ return picking_obj.create(cr, uid, self._prepare_chained_picking(cr, uid, picking_name, picking, picking_type, moves_todo, context=context))
+
def create_chained_picking(self, cr, uid, moves, context=None):
res_obj = self.pool.get('res.company')
location_obj = self.pool.get('stock.location')
else:
acc_dest = accounts['stock_account_output']
- acc_variation = accounts.get('property_stock_variation', False)
+ acc_valuation = accounts.get('property_stock_valuation_account_id', False)
journal_id = accounts['stock_journal']
- if acc_dest == acc_variation:
- raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Output Account defined on this product and Variant account on category of this product are same.'))
+ if acc_dest == acc_valuation:
+ raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Output Account defined on this product and Valuation account on category of this product are same.'))
- if acc_src == acc_variation:
- raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Input Account defined on this product and Variant account on category of this product are same.'))
+ if acc_src == acc_valuation:
+ raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Input Account defined on this product and Valuation account on category of this product are same.'))
if not acc_src:
raise osv.except_osv(_('Error!'), _('There is no stock input account defined for this product or its category: "%s" (id: %d)') % \
if not journal_id:
raise osv.except_osv(_('Error!'), _('There is no journal defined on the product category: "%s" (id: %d)') % \
(move.product_id.categ_id.name, move.product_id.categ_id.id,))
- if not acc_variation:
- raise osv.except_osv(_('Error!'), _('There is no inventory variation account defined on the product category: "%s" (id: %d)') % \
+ if not acc_valuation:
+ raise osv.except_osv(_('Error!'), _('There is no inventory Valuation account defined on the product category: "%s" (id: %d)') % \
(move.product_id.categ_id.name, move.product_id.categ_id.id,))
- return journal_id, acc_src, acc_dest, acc_variation
+ return journal_id, acc_src, acc_dest, acc_valuation
def _get_reference_accounting_values_for_valuation(self, cr, uid, move, context=None):
"""
if move.location_id.company_id \
and (move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal'\
or move.location_id.company_id != move.location_dest_id.company_id):
- journal_id, acc_src, acc_dest, acc_variation = self._get_accounting_data_for_valuation(cr, uid, move, src_company_ctx)
+ journal_id, acc_src, acc_dest, acc_valuation = self._get_accounting_data_for_valuation(cr, uid, move, src_company_ctx)
reference_amount, reference_currency_id = self._get_reference_accounting_values_for_valuation(cr, uid, move, src_company_ctx)
- account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_variation, acc_dest, reference_amount, reference_currency_id, context))]
+ account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_valuation, acc_dest, reference_amount, reference_currency_id, context))]
# Incoming moves (or cross-company input part)
if move.location_dest_id.company_id \
and (move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal'\
or move.location_id.company_id != move.location_dest_id.company_id):
- journal_id, acc_src, acc_dest, acc_variation = self._get_accounting_data_for_valuation(cr, uid, move, dest_company_ctx)
+ journal_id, acc_src, acc_dest, acc_valuation = self._get_accounting_data_for_valuation(cr, uid, move, dest_company_ctx)
reference_amount, reference_currency_id = self._get_reference_accounting_values_for_valuation(cr, uid, move, src_company_ctx)
- account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_src, acc_variation, reference_amount, reference_currency_id, context))]
+ account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_src, acc_valuation, reference_amount, reference_currency_id, context))]
move_obj = self.pool.get('account.move')
for j_id, move_lines in account_moves:
""" Makes the move done and if all moves are done, it will finish the picking.
@return:
"""
- partial_datas=''
picking_ids = []
move_ids = []
- partial_obj=self.pool.get('stock.partial.picking')
wf_service = netsvc.LocalService("workflow")
- partial_id=partial_obj.search(cr,uid,[])
- if partial_id:
- partial_datas = partial_obj.read(cr, uid, partial_id, context=context)[0]
if context is None:
context = {}
self.action_done(cr, uid, [move.move_dest_id.id], context=context)
self._create_product_valuation_moves(cr, uid, move, context=context)
- prodlot_id = partial_datas and partial_datas.get('move%s_prodlot_id' % (move.id), False)
- if prodlot_id:
- self.write(cr, uid, [move.id], {'prodlot_id': prodlot_id}, context=context)
if move.state not in ('confirmed','done','assigned'):
todo.append(move.id)
return super(stock_move, self).unlink(
cr, uid, ids, context=ctx)
+ # _create_lot function is not used anywhere
def _create_lot(self, cr, uid, ids, product_id, prefix=False):
""" Creates production lot
@return: Production lot id
@param context: context arguments
@return: Scraped lines
"""
+ #quantity should in MOVE UOM
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide a positive quantity to scrap!'))
res = []
res += [new_move]
product_obj = self.pool.get('product.product')
for (id, name) in product_obj.name_get(cr, uid, [move.product_id.id]):
- self.log(cr, uid, move.id, "%s x %s %s" % (move.product_qty, name, _("were scrapped")))
+ self.log(cr, uid, move.id, "%s x %s %s" % (quantity, name, _("were scrapped")))
- self.action_done(cr, uid, res)
+ self.action_done(cr, uid, res, context=context)
return res
+ # action_split function is not used anywhere
def action_split(self, cr, uid, ids, quantity, split_by_qty=1, prefix=False, with_lot=True, context=None):
""" Split Stock Move lines into production lot which specified split by quantity.
@param cr: the database cursor
@param context: context arguments
@return: Consumed lines
"""
+ #quantity should in MOVE UOM
if context is None:
context = {}
if quantity <= 0:
quantity = move.product_qty
uos_qty = quantity / move_qty * move.product_uos_qty
-
+ location_dest_id = move.product_id.property_stock_production or move.location_dest_id
if quantity_rest > 0:
default_val = {
'product_qty': quantity,
'product_uos_qty': uos_qty,
'state': move.state,
'location_id': location_id or move.location_id.id,
+ 'location_dest_id': location_dest_id.id,
}
current_move = self.copy(cr, uid, move.id, default_val)
res += [current_move]
update_val = {
'product_qty' : quantity_rest,
'product_uos_qty' : uos_qty_rest,
- 'location_id': location_id or move.location_id.id
+ 'location_id': location_id or move.location_id.id,
+ 'location_dest_id': location_dest_id.id,
}
self.write(cr, uid, [move.id], update_val)
for (id, name) in product_obj.name_get(cr, uid, [new_move.product_id.id]):
message = _("Product '%s' is consumed with '%s' quantity.") %(name, new_move.product_qty)
self.log(cr, uid, new_move.id, message)
- self.action_done(cr, uid, res)
+ self.action_done(cr, uid, res, context=context)
return res
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c)
}
+ def copy(self, cr, uid, id, default=None, context=None):
+ if default is None:
+ default = {}
+ default = default.copy()
+ default.update({'move_ids': [], 'date_done': False})
+ return super(stock_inventory, self).copy(cr, uid, id, default, context=context)
+
def _inventory_line_hook(self, cr, uid, inventory_line, move_vals):
""" Creates a stock move from an inventory line
@param inventory_line:
message = _("Inventory '%s' is done.") %(inv.name)
self.log(cr, uid, inv.id, message)
self.write(cr, uid, [inv.id], {'state': 'confirm', 'move_ids': [(6, 0, move_ids)]})
+ self.pool.get('stock.move').action_confirm(cr, uid, move_ids, context=context)
return True
def action_cancel_draft(self, cr, uid, ids, context=None):
self.write(cr, uid, [inv.id], {'state':'draft'}, context=context)
return True
- def action_cancel_inventary(self, cr, uid, ids, context=None):
+ def action_cancel_inventory(self, cr, uid, ids, context=None):
""" Cancels both stock move and inventory
@return: True
"""
for account_move in account_move_data_l:
if account_move['state'] == 'posted':
raise osv.except_osv(_('UserError'),
- _('You can not cancel inventory which has any account move with posted state.'))
+ _('In order to cancel this inventory, you must first unpost related journal entries.'))
account_move_obj.unlink(cr, uid, [account_move['id']], context=context)
self.write(cr, uid, [inv.id], {'state': 'cancel'}, context=context)
return True
return {'value': {'product_qty': 0.0, 'product_uom': False}}
obj_product = self.pool.get('product.product').browse(cr, uid, product)
uom = uom or obj_product.uom_id.id
- amount = self.pool.get('stock.location')._product_get(cr, uid, location_id, [product], {'uom': uom, 'to_date': to_date})[product]
+ amount = self.pool.get('stock.location')._product_get(cr, uid, location_id, [product], {'uom': uom, 'to_date': to_date, 'compute_child': False})[product]
result = {'product_qty': amount, 'product_uom': uom}
return {'value': result}
'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
'partner_address_id': fields.many2one('res.partner.address', 'Owner Address'),
'lot_input_id': fields.many2one('stock.location', 'Location Input', required=True, domain=[('usage','<>','view')]),
- 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage','<>','view')]),
+ 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage','=','internal')]),
'lot_output_id': fields.many2one('stock.location', 'Location Output', required=True, domain=[('usage','<>','view')]),
}
_defaults = {