[WIP] commit before the weekend, not sure everything is working as expected
bzr revid: qdp-launchpad@openerp.com-20130719171514-1f9whgnp1b2s64nk
This commit is contained in:
+40
-26
@@ -695,28 +695,42 @@ class stock_picking(osv.osv):
|
||||
return done_reserved_quants
|
||||
|
||||
#TODO move this in another class?
|
||||
def make_packaging(self, cr, uid, picking_id, move, possible_quants, context=None):
|
||||
def make_packaging(self, cr, uid, picking_id, todo_move_ids, context=None):
|
||||
stock_operation_obj = self.pool.get('stock.pack.operation')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
quant_obj = self.pool.get('stock.quant')
|
||||
operation_ids = stock_operation_obj.find_packaging_op_from_product(cr, uid, move.product_id, picking_id, context=context)
|
||||
for op in stock_operation_obj.browse(cr, uid, operation_ids, context=context):
|
||||
if not op.result_package_id:
|
||||
continue
|
||||
if op.product_id:
|
||||
quant_tuples = quant_obj._get_quant_tuples(cr, uid, possible_quants, op.product_qty, context=context)
|
||||
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
|
||||
quant_obj.write(cr, uid, [qt[O] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
|
||||
elif op.quant_id:
|
||||
quant_tuples = quant_obj._get_quant_tuples(cr, uid, [op.quant_id.id], op.product_qty, context=context)
|
||||
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
|
||||
quant_obj.write(cr, uid, [qt[O] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
|
||||
elif op.package_id:
|
||||
#pack existing packs
|
||||
self.pool.get('stock.quant.package').write(cr, uid, op.package_id.id, {'parent_id': op.result_package_id.id}, context=context)
|
||||
for move in move_obj.browse(cr, uid, todo_move_ids, context=context):
|
||||
operation_ids = stock_operation_obj.find_packaging_op_from_product(cr, uid, move.product_id, picking_id, context=context)
|
||||
possible_quants = [q.id for q in move.quant_ids]
|
||||
for op in stock_operation_obj.browse(cr, uid, operation_ids, context=context):
|
||||
if not op.result_package_id:
|
||||
continue
|
||||
if op.product_id:
|
||||
quant_tuples = quant_obj._get_quant_tuples(cr, uid, possible_quants, op.product_qty, context=context)
|
||||
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
|
||||
quant_obj.write(cr, uid, [qt[0] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
|
||||
elif op.quant_id:
|
||||
quant_tuples = quant_obj._get_quant_tuples(cr, uid, [op.quant_id.id], op.product_qty, context=context)
|
||||
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
|
||||
quant_obj.write(cr, uid, [qt[0] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
|
||||
elif op.package_id:
|
||||
#pack existing packs
|
||||
self.pool.get('stock.quant.package').write(cr, uid, op.package_id.id, {'parent_id': op.result_package_id.id}, context=context)
|
||||
|
||||
|
||||
#TODO: check more in depth that the partial picking is working, then remove this bunch of code
|
||||
# def do_partial(self, cr, uid, ids, partial_datas, context=None):
|
||||
def do_partial(self, cr, uid, picking_id, partial_datas, only_split_lines=False, context=None):
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
proc_group = self.pool.get("procurement.group")
|
||||
group_id = proc_group.create(cr, uid, {}, context=context)
|
||||
todo_move_ids = []
|
||||
for partial_data in partial_datas:
|
||||
todo_move_ids += [stock_move_obj.do_partial(cr, uid, partial_data.get('move_id'), partial_data, group_id, context=context)]
|
||||
ctx = context.copy()
|
||||
ctx.update({'backorder_of': picking_id})
|
||||
stock_move_obj.action_confirm(cr, uid, todo_move_ids, context=ctx)
|
||||
if not only_split_lines:
|
||||
stock_move_obj.action_done(cr, uid, todo_move_ids, context=context)
|
||||
self.make_packaging(cr, uid, picking_id, todo_move_ids, context=context)
|
||||
|
||||
# """ Makes partial picking and moves done.
|
||||
# @param partial_datas : Dictionary containing details of partial picking
|
||||
# like partner_id, partner_id, delivery_date,
|
||||
@@ -1501,11 +1515,12 @@ class stock_move(osv.osv):
|
||||
pick_obj = self.pool.get("stock.picking")
|
||||
sequence_obj = self.pool.get('ir.sequence')
|
||||
picks = pick_obj.search(cr, uid, [('group_id', '=', move.group_id.id), ('location_id', '=', move.location_id.id),
|
||||
('location_dest_id', '=', move.location_dest_id.id), ('state', 'in', ['confirmed', 'waiting', 'draft']), ('partner_id', '=', move.partner_id.id)], context=context)
|
||||
('location_dest_id', '=', move.location_dest_id.id), ('state', 'in', ['confirmed', 'waiting', 'draft'])], context=context)
|
||||
if picks:
|
||||
pick = picks[0]
|
||||
else:
|
||||
if context.get('backorder_of'):
|
||||
#copy the original picking
|
||||
original_picking = pick_obj.browse(cr, uid, context.get('backorder_of'), context=context)
|
||||
new_picking_name = original_picking.name
|
||||
back_order_name = sequence_obj.get(cr, uid, 'stock.picking.%s' % (original_picking.type))
|
||||
@@ -1514,7 +1529,8 @@ class stock_move(osv.osv):
|
||||
'move_lines': [],
|
||||
'state': 'draft'})
|
||||
pick_obj.message_post(cr, uid, original_picking.id, body=_("Back order <em>%s</em> has been <b>created</b>.") % (back_order_name), context=context)
|
||||
pick_obj.write(cr, uid, [original_picking.id], {'backorder_id': pick})
|
||||
unlink_operation_order = [(2, op.id) for op in original_picking.pack_operation_ids]
|
||||
pick_obj.write(cr, uid, [original_picking.id], {'backorder_id': pick, 'pack_operation_ids': unlink_operation_order}, context=context)
|
||||
else:
|
||||
#a backorder picking doesn't exist yet, create a new one
|
||||
values = {'origin': move.origin,
|
||||
@@ -1890,7 +1906,6 @@ class stock_move(osv.osv):
|
||||
# product_avail[product.id] += product_uom_qty
|
||||
# return res
|
||||
|
||||
# FIXME: needs refactoring, this code is partially duplicated in stock_picking.do_partial()!
|
||||
def do_partial(self, cr, uid, move_id, partial_data, move_group_id, context=None):
|
||||
""" Partially (or not) moves a stock.move.
|
||||
@param partial_datas: Dictionary containing details of partial picking
|
||||
@@ -1902,9 +1917,6 @@ class stock_move(osv.osv):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
complete, too_many, too_few = [], [], []
|
||||
move_product_qty, lot_ids, partial_qty, product_uoms = {}, {}, {}, {}
|
||||
|
||||
move = self.browse(cr, uid, move_id, context=context)
|
||||
product_uom_qty = partial_data.get('product_uom_qty', 0.0)
|
||||
product_uom = partial_data.get('product_uom', False)
|
||||
@@ -1928,7 +1940,9 @@ class stock_move(osv.osv):
|
||||
#without_rounding_qty = (wizard_line.quantity / line_uom.factor) * initial_uom.factor
|
||||
#if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
|
||||
# raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only roundings of "%s %s" are accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
|
||||
|
||||
##Quantity must be Positive
|
||||
#if wizard_line.quantity < 0:
|
||||
# raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.'))
|
||||
|
||||
#partial_qty is the quantity processed in the normalized product uom
|
||||
partial_qty = uom_obj._compute_qty(cr, uid, product_uom, product_uom_qty, move.product_id.uom_id.id)
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
<field name="product_id" />
|
||||
<field name="quantity" />
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="location_id" />
|
||||
<field name="location_dest_id" />
|
||||
<field name="lot_id" domain="[('product_id', '=', product_id)]" groups="stock.group_production_lot"/>
|
||||
<field name="update_cost" invisible="1"/>
|
||||
<field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
|
||||
@@ -58,8 +56,6 @@
|
||||
<field name="product_id" />
|
||||
<field name="quantity" />
|
||||
<field name="product_uom" />
|
||||
<field name="location_id" />
|
||||
<field name="location_dest_id" />
|
||||
<field name="lot_id" domain="[('product_id', '=', product_id)]"/>
|
||||
<field name="update_cost" invisible="1"/>
|
||||
<field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
|
||||
|
||||
@@ -31,6 +31,8 @@ class stock_partial_picking_line(osv.TransientModel):
|
||||
def _tracking(self, cursor, user, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for tracklot in self.browse(cursor, user, ids, context=context):
|
||||
if not tracklot.move_id:
|
||||
continue
|
||||
tracking = False
|
||||
if (tracklot.move_id.picking_id.type == 'in' and tracklot.product_id.track_incoming) or \
|
||||
(tracklot.move_id.picking_id.type == 'out' and tracklot.product_id.track_outgoing):
|
||||
@@ -45,9 +47,7 @@ class stock_partial_picking_line(osv.TransientModel):
|
||||
'quantity': fields.float("Quantity", digits_compute=dp.get_precision('Product Unit of Measure'), required=True),
|
||||
'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True, ondelete='CASCADE'),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Serial Number', ondelete='CASCADE'),
|
||||
'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete='CASCADE', domain=[('usage', '<>', 'view')]),
|
||||
'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True, ondelete='CASCADE', domain=[('usage', '<>', 'view')]),
|
||||
'move_id': fields.many2one('stock.move', "Move", ondelete='CASCADE'), # TODO: check if should be required or not
|
||||
'move_id': fields.many2one('stock.move', "Move", ondelete='CASCADE'),
|
||||
'wizard_id': fields.many2one('stock.partial.picking', string="Wizard", ondelete='CASCADE'),
|
||||
'update_cost': fields.boolean('Need cost update'),
|
||||
'cost': fields.float("Cost", help="Unit Cost for this product line"),
|
||||
@@ -79,6 +79,7 @@ class stock_partial_picking(osv.osv_memory):
|
||||
'move_ids': fields.one2many('stock.partial.picking.line', 'wizard_id', 'Product Moves'),
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking', required=True, ondelete='CASCADE'),
|
||||
'hide_tracking': fields.function(_hide_tracking, string='Tracking', type='boolean', help='This field is for internal purpose. It is used to decide if the column production lot has to be shown on the moves or not.'),
|
||||
'only_split_lines': fields.boolean('Only Split', help="Check this field if you just want to split the picking and don't want to marke as done the lines in the backorder"),
|
||||
}
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
@@ -114,10 +115,10 @@ class stock_partial_picking(osv.osv_memory):
|
||||
return res
|
||||
assert active_model in ('stock.picking', 'stock.picking.in', 'stock.picking.out'), 'Bad context propagation'
|
||||
picking_id, = picking_ids
|
||||
picking = self.pool.get('stock.picking').browse(cr, uid, picking_id, context=context)
|
||||
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:
|
||||
@@ -140,51 +141,42 @@ class stock_partial_picking(osv.osv_memory):
|
||||
assert len(ids) == 1, 'Partial picking processing may only be done one at a time.'
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
proc_group = self.pool.get("procurement.group")
|
||||
#uom_obj = self.pool.get('product.uom')
|
||||
partial = self.browse(cr, uid, ids[0], context=context)
|
||||
partial_data = {
|
||||
'delivery_date': partial.date
|
||||
}
|
||||
group_id = proc_group.create(cr, uid, {}, context=context)
|
||||
partial_wizard = self.browse(cr, uid, ids[0], context=context)
|
||||
picking_id = partial_wizard.picking_id.id
|
||||
assert picking_id, 'Picking not defined'
|
||||
picking_type = partial_wizard.picking_id.type
|
||||
|
||||
todo_move_ids = []
|
||||
for wizard_line in partial.move_ids:
|
||||
#Quantity must be Positive
|
||||
if wizard_line.quantity < 0:
|
||||
raise osv.except_osv(_('Warning!'), _('Please provide proper Quantity.'))
|
||||
partial_data = {
|
||||
'delivery_date': partial_wizard.date
|
||||
}
|
||||
|
||||
partial_datas = []
|
||||
for wizard_line in partial_wizard.move_ids:
|
||||
move_id = wizard_line.move_id.id
|
||||
if not move_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': wizard_line.product_id.id,
|
||||
'product_uom_qty': wizard_line.quantity,
|
||||
'product_uom': wizard_line.product_uom.id,
|
||||
'lot_id': wizard_line.lot_id.id,
|
||||
'location_id': partial_wizard.picking_id.location_id.id,
|
||||
'location_dest_id': partial_wizard.picking_id.location_dest_id.id,
|
||||
'picking_id': False,
|
||||
'price_unit': wizard_line.cost}, context=context)
|
||||
partial_data.update({
|
||||
'product_id': wizard_line.product_id.id,
|
||||
'product_uom_qty': wizard_line.quantity,
|
||||
'product_uom': wizard_line.product_uom.id,
|
||||
'lot_id': wizard_line.lot_id.id,
|
||||
'price_unit': wizard_line.cost,
|
||||
'move_id': move_id,
|
||||
})
|
||||
|
||||
move_id = wizard_line.move_id.id
|
||||
#if not move_id:
|
||||
# #TODO: check this out. Do we really need (want?) to support this case since the lot number is on the quant? we may want to raise an error instead...
|
||||
# picking_type = partial.picking_id.type
|
||||
# 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': wizard_line.product_id.id,
|
||||
# 'product_qty': wizard_line.quantity,
|
||||
# 'product_uom': wizard_line.product_uom.id,
|
||||
# 'lot_id': wizard_line.lot_id.id,
|
||||
# 'location_id': wizard_line.location_id.id,
|
||||
# 'location_dest_id': wizard_line.location_dest_id.id,
|
||||
# 'picking_id': partial.picking_id.id,
|
||||
# 'price_unit': wizard_line.cost}, context=context)
|
||||
# stock_move_obj.action_confirm(cr, uid, [move_id], context)
|
||||
todo_move_ids += [stock_move_obj.do_partial(cr, uid, move_id, partial_data, group_id, context=context)]
|
||||
picking_ids = context.get('active_ids')
|
||||
picking_id = picking_ids and picking_ids[0] or context.get('active_id')
|
||||
ctx = context.copy()
|
||||
ctx.update({'backorder_of': picking_id})
|
||||
stock_move_obj.action_confirm(cr, uid, todo_move_ids, context=ctx)
|
||||
stock_move_obj.action_done(cr, uid, todo_move_ids, context=context)
|
||||
tmp = partial_data.copy()
|
||||
partial_datas += [tmp]
|
||||
self.pool.get('stock.picking').do_partial(cr, uid, picking_id, partial_datas, partial_wizard.only_split_lines, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -65,8 +65,6 @@
|
||||
<field name="product_id" />
|
||||
<field name="quantity" />
|
||||
<field name="product_uom" />
|
||||
<field name="location_id" />
|
||||
<field name="location_dest_id" />
|
||||
<field name="tracking" invisible="1"/>
|
||||
<field name="lot_id" domain="[('product_id', '=', product_id)]" attrs="{'required':[('tracking','=',True)]}"/>
|
||||
<field name="update_cost" invisible="1"/>
|
||||
|
||||
Reference in New Issue
Block a user