class stock_partial_picking(osv.osv_memory):
_name = "stock.partial.picking"
- _description = "Partial Picking"
+ _description = "Partial Picking Processing Wizard"
_columns = {
'date': fields.datetime('Date', required=True),
- 'product_moves_out' : fields.one2many('stock.move.memory.out', 'wizard_id', 'Moves'),
- 'product_moves_in' : fields.one2many('stock.move.memory.in', 'wizard_id', 'Moves'),
+ 'move_ids' : fields.one2many('stock.partial.picking.line', 'wizard_id', 'Product Moves'),
+ 'picking_id': fields.many2one('stock.picking', 'Picking', required=True, ondelete='CASCADE'),
}
-
- def get_picking_type(self, cr, uid, picking, context=None):
- picking_type = picking.type
- for move in picking.move_lines:
- if picking.type == 'in' and move.product_id.cost_method == 'average':
- picking_type = 'in'
- break
- else:
- picking_type = 'out'
- return picking_type
-
+
def default_get(self, cr, uid, fields, context=None):
- """ To get default values for the object.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- if context is None:
- context = {}
-
- pick_obj = self.pool.get('stock.picking')
+ if context is None: context = {}
res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
picking_ids = context.get('active_ids', [])
- if not picking_ids:
+ if not picking_ids or (not context.get('active_model') == 'stock.picking') \
+ or len(picking_ids) != 1:
+ # Partial Picking Processing may only be done for one picking at a time
return res
-
- result = []
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- pick_type = self.get_picking_type(cr, uid, pick, context=context)
- for m in pick.move_lines:
- if m.state in ('done', 'cancel'):
- continue
- if m.state == 'assigned':
- result.append(self.__create_partial_picking_memory(m, pick_type))
-
- if 'product_moves_in' in fields:
- res.update({'product_moves_in': result})
- if 'product_moves_out' in fields:
- res.update({'product_moves_out': result})
+ picking_id, = picking_ids
+ if 'picking_id' in fields:
+ res.update(picking_id=picking_id)
+ if 'move_ids' in fields:
+ picking = self.pool.get('stock.picking').browse(cr, uid, picking_id, context=context)
+ moves = [self._partial_move_for(cr, uid, m) for m in picking.move_lines if m.state not in ('done','cancel')]
+ res.update(move_ids=moves)
if 'date' in fields:
- res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
+ res.update(date=time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
return res
-
- def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
- result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
-
- pick_obj = self.pool.get('stock.picking')
- picking_ids = context.get('active_ids', False)
-
- if not picking_ids:
- # not called through an action (e.g. buildbot), return the default.
- return result
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- picking_type = self.get_picking_type(cr, uid, pick, context=context)
+ def _product_cost_for_average_update(self, cr, uid, move):
+ """Returns product cost and currency ID for the given move, suited for re-computing
+ the average product cost.
++<<<<<<< TREE
+ _moves_arch_lst = """<form string="%s">
+ <field name="date" invisible="1"/>
+ <separator colspan="4" string="%s"/>
+ <field name="%s" colspan="4" nolabel="1" mode="tree,form" width="550" height="200" ></field>
+ """ % (_('Process Document'), _('Products'), "product_moves_" + picking_type)
+ _moves_fields = result['fields']
+
+ # add field related to picking type only
+ _moves_fields.update({
+ 'product_moves_' + picking_type: {'relation': 'stock.move.memory.'+picking_type, 'type' : 'one2many', 'string' : 'Product Moves'},
+ })
+ _moves_arch_lst += """
+ <separator string="" colspan="4" />
+ <label string="" colspan="2"/>
+ <group col="2" colspan="2">
+ <button icon='gtk-cancel' special="cancel"
+ string="_Cancel" />
+ <button name="do_partial" string="_Validate"
+ colspan="1" type="object" icon="gtk-go-forward" />
+ </group>
+ </form>"""
+ result['arch'] = _moves_arch_lst
+ result['fields'] = _moves_fields
+ return result
+
+ def __create_partial_picking_memory(self, picking, pick_type):
+ move_memory = {
+ 'product_id' : picking.product_id.id,
+ 'quantity' : picking.product_qty,
+ 'product_uom' : picking.product_uom.id,
+ 'prodlot_id' : picking.prodlot_id.id,
+ 'move_id' : picking.id,
+ 'location_id' : picking.location_id.id,
+ 'location_dest_id' : picking.location_dest_id.id,
++=======
+ :return: map of the form::
+
+ {'cost': 123.34,
+ 'currency': 42}
+ """
+ # Currently, the cost on the product form is supposed to be expressed in the currency
+ # of the company owning the product. If not set, we fall back to the picking's company,
+ # which should work in simple cases.
+ return {'cost': move.product_id.standard_price,
+ 'currency': move.product_id.company_id.currency_id.id \
+ or move.picking_id.company_id.currency_id.id \
+ or False}
+
+ def _partial_move_for(self, cr, uid, move):
+ partial_move = {
+ 'product_id' : move.product_id.id,
+ 'quantity' : move.product_qty,
+ 'product_uom' : move.product_uom.id,
+ 'prodlot_id' : move.prodlot_id.id,
+ 'move_id' : move.id,
+ 'location_id' : move.location_id.id,
+ 'location_dest_id' : move.location_dest_id.id,
++>>>>>>> MERGE-SOURCE
}
-
- if pick_type == 'in':
- move_memory.update({
- 'cost' : picking.product_id.standard_price,
- 'currency' : picking.product_id.company_id and picking.product_id.company_id.currency_id and picking.product_id.company_id.currency_id.id or False,
- })
- return move_memory
+ if move.picking_id.type == 'in' and move.product_id.cost_method == 'average':
+ partial_move.update(update_cost=True, **self._product_cost_for_average_update(cr, uid, move))
+ return partial_move
def do_partial(self, cr, uid, ids, context=None):
- """ Makes partial moves and pickings done.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- pick_obj = self.pool.get('stock.picking')
- stock_move_obj = self.pool.get('stock.move')
- picking_ids = context.get('active_ids', False)
+ assert len(ids) == 1, 'Partial picking processing may only be done one at a time'
+ stock_picking = self.pool.get('stock.picking')
+ stock_move = self.pool.get('stock.move')
partial = self.browse(cr, uid, ids[0], context=context)
- partial_datas = {
+ partial_data = {
'delivery_date' : partial.date
}
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- picking_type = self.get_picking_type(cr, uid, pick, context=context)
- moves_list = picking_type == 'in' and partial.product_moves_in or partial.product_moves_out
- for move in moves_list:
- if not move.move_id.id:
- seq_obj_name = 'stock.picking.' + picking_type
- move_id = stock_move_obj.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
- 'product_id': move.product_id.id,
- 'product_qty': move.quantity,
- 'product_uom': move.product_uom.id,
- 'prodlot_id': move.prodlot_id.id,
- 'location_id' : move.location_id.id,
- 'location_dest_id' : move.location_dest_id.id,
- 'picking_id': pick.id
- },context=context)
- stock_move_obj.action_done(cr, uid, [move_id], context)
- else:
- move_id = move.move_id.id
-
- partial_datas['move%s' % (move_id)] = {
- 'product_id': move.product_id.id,
- 'product_qty': move.quantity,
- 'product_uom': move.product_uom.id,
- 'prodlot_id': move.prodlot_id.id,
- }
- if (picking_type == 'in') and (move.product_id.cost_method == 'average'):
- partial_datas['move%s' % (move.move_id.id)].update({
- 'product_price' : move.cost,
- 'product_currency': move.currency.id,
- })
- pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
+ picking_type = partial.picking_id.type
+ for move in partial.move_ids:
+ move_id = move.move_id.id
+ if not move_id:
+ seq_obj_name = 'stock.picking.' + picking_type
+ move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
+ 'product_id': move.product_id.id,
+ 'product_qty': move.quantity,
+ 'product_uom': move.product_uom.id,
+ 'prodlot_id': move.prodlot_id.id,
+ 'location_id' : move.location_id.id,
+ 'location_dest_id' : move.location_dest_id.id,
+ 'picking_id': partial.picking_id.id
+ },context=context)
+ stock_move.action_done(cr, uid, [move_id], context)
+ partial_data['move%s' % (move_id)] = {
+ 'product_id': move.product_id.id,
+ 'product_qty': move.quantity,
+ 'product_uom': move.product_uom.id,
+ 'prodlot_id': move.prodlot_id.id,
+ }
+ if (picking_type == 'in') and (move.product_id.cost_method == 'average'):
+ partial_data['move%s' % (move.move_id.id)].update(product_price=move.cost,
+ product_currency=move.currency.id)
+ stock_picking.do_partial(cr, uid, [partial.picking_id.id], partial_data, context=context)
return {'type': 'ir.actions.act_window_close'}
- stock_partial_picking()
-
- # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+ # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: