[REF] refactoring made during code review. Some optimization patches have been rewritten more clearly, others abandonned or kept. WIP

bzr revid: qdp-launchpad@openerp.com-20140319163359-2ea7tjn5ba1ggein
This commit is contained in:
Quentin (OpenERP) 2014-03-19 17:33:59 +01:00
parent 5300ff660c
commit bde6b6d6e5
7 changed files with 117 additions and 158 deletions

View File

@ -807,10 +807,9 @@ class product_product(osv.osv):
result = []
for product in self.browse(cr, SUPERUSER_ID, ids, context=context):
sellers = []
if partner_id:
sellers = filter(lambda x: x.name.id == partner_id, product.seller_ids)
else:
sellers = False
if sellers:
for s in sellers:
mydict = {

View File

@ -35,7 +35,7 @@ class stock_move(osv.osv):
ids = [ids]
res = super(stock_move, self).write(cr, uid, ids, vals, context=context)
from openerp import workflow
if 'state' in vals and vals['state'] in ['done', 'cancel']:
if vals.get('state') in ['done', 'cancel']:
for move in self.browse(cr, uid, ids, context=context):
if move.purchase_line_id and move.purchase_line_id.order_id:
order_id = move.purchase_line_id.order_id.id

View File

@ -4,4 +4,4 @@
I duplicate order.
-
!python {model: purchase.order}: |
self.copy_data(cr, uid, ref('purchase_order_1'), context)
self.copy(cr, uid, ref('purchase_order_1'), context)

View File

@ -702,7 +702,11 @@ class sale_order(osv.osv):
proc_ids.append(proc_id)
#Confirm procurement order such that rules will be applied on it
#note that the workflow normally ensure proc_ids isn't an empty list
import time;
a = time.time()
procurement_obj.run(cr, uid, proc_ids, context=context)
b = time.time()
print "total time in procurement run", b-a
#if shipping was in exception and the user choose to recreate the delivery order, write the new status of SO
if order.state == 'shipping_except':

View File

@ -221,16 +221,15 @@ class procurement_order(osv.osv):
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def run(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
res = super(procurement_order, self).run(cr, uid, ids, context=context)
#after all the procurements are run, check if some created a draft stock move that needs to be confirmed
#(we do that in batch because it fasten the picking assignation and the picking state computation)
#(we do that in batch because it fasts the picking assignation and the picking state computation)
move_to_confirm_ids = []
for procurement in self.browse(cr, uid, ids, context=context):
if procurement.state == "running" and procurement.rule_id and procurement.rule_id.action == "move":
move_to_confirm_ids += [m.id for m in procurement.move_ids if m.state == 'draft']
if move_to_confirm_ids:
move_obj.action_confirm(cr, uid, move_to_confirm_ids, context=context)
self.pool.get('stock.move').action_confirm(cr, uid, move_to_confirm_ids, context=context)
return res
def _check(self, cr, uid, procurement, context=None):

View File

@ -61,6 +61,10 @@ class stock_location(osv.osv):
_order = 'parent_left'
_rec_name = 'complete_name'
def _location_owner(self, cr, uid, location, context=None):
''' Return the company owning the location if any '''
return location and (location.usage == 'internal') and location.company_id or False
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
@ -325,7 +329,6 @@ class stock_quant(osv.osv):
elif reserved_availability > 0 and not move.partially_available:
self.pool.get('stock.move').write(cr, uid, [move.id], {'partially_available': True}, context=context)
def quants_move(self, cr, uid, quants, move, location_to, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, context=None):
"""Moves all given stock.quant in the given destination location.
:param quants: list of tuple(browse record(stock.quant) or None, quantity to move)
@ -337,38 +340,37 @@ class stock_quant(osv.osv):
:param dest_package_id: ID of the package that must be set on the moved quant
"""
quants_reconcile = []
quants_move = []
to_move_quants = []
self._check_location(cr, uid, location_to, context=context)
for quant, qty in quants:
if not quant:
#If quant is None, we will create a quant to move (and potentially a negative counterpart too)
quant = self._quant_create(cr, uid, qty, move, lot_id=lot_id, owner_id=owner_id, src_package_id=src_package_id, dest_package_id=dest_package_id, force_location = location_to, context=context)
quant = self._quant_create(cr, uid, qty, move, lot_id=lot_id, owner_id=owner_id, src_package_id=src_package_id, dest_package_id=dest_package_id, force_location=location_to, context=context)
else:
quants_move += [(quant, qty)]
self._quant_split(cr, uid, quant, qty, context=context)
quant.refresh()
to_move_quants.append(quant)
quants_reconcile.append(quant)
if quants_move:
self.move_single_quant_tuples(cr, uid, quants_move, move, location_to, dest_package_id, context=context)
self._quants_reconcile_negative(cr, uid, quants_reconcile, move, context=context)
def move_single_quant_tuples(self, cr, uid, quants, move, location_dest_id, dest_package_id, context=None):
whole_quants = []
for quant, qty in quants:
new_quant = self._quant_split(cr, uid, quant, qty, context=context)
quant.refresh()
whole_quants.append(quant.id)
if whole_quants:
vals = {'location_id': location_dest_id.id,
'history_ids': [(4, move.id)],
'package_id': dest_package_id}
self.write(cr, SUPERUSER_ID, whole_quants, vals, context=context)
if to_move_quants:
self.move_quants_write(cr, uid, to_move_quants, move, location_to, dest_package_id, context=context)
if location_to.usage == 'internal':
if self.search(cr, uid, [('product_id', '=', move.product_id.id), ('qty','<', 0)], limit=1, context=context):
for quant in quants_reconcile:
quant.refresh()
self._quant_reconcile_negative(cr, uid, quant, move, context=context)
def move_quants_write(self, cr, uid, quants, move, location_dest_id, dest_package_id, context=None):
vals = {'location_id': location_dest_id.id,
'history_ids': [(4, move.id)],
'package_id': dest_package_id}
self.write(cr, SUPERUSER_ID, [q.id for q in quants], vals, context=context)
def quants_get_prefered_domain(self, cr, uid, location, product, qty, domain=None, prefered_domain=False, fallback_domain=False, restrict_lot_id=False, restrict_partner_id=False, context=None):
''' This function tries to find quants in the given location for the given domain, by trying to first limit
the choice on the quants that match the prefered_domain as well. But if the qty requested is not reached
it tries to find the remaining quantity by using the fallback_domain.
'''
#don't look for quants in location that are of type production, supplier or inventory.
if location.usage in ['inventory', 'production', 'supplier']:
return [(None, qty)]
if prefered_domain and fallback_domain:
@ -475,16 +477,6 @@ class stock_quant(osv.osv):
path.append((4, move.id))
self.write(cr, SUPERUSER_ID, solved_quant_ids, {'history_ids': path}, context=context)
def _quants_reconcile_negative(self, cr, uid, quants, move, context=None):
if quants[0].location_id.usage != 'internal':
return False
quants_rec = self.search(cr, uid, [('product_id', '=', move.product_id.id), ('qty','<', 0)], limit=1, context=context)
if quants_rec:
for quant in quants:
quant.refresh()
self._quant_reconcile_negative(cr, uid, quant, move, context=context)
def _quant_reconcile_negative(self, cr, uid, quant, move, context=None):
"""
When new quant arrive in a location, try to reconcile it with
@ -551,7 +543,6 @@ class stock_quant(osv.osv):
domain += [('company_id', '=', context.get('force_company'))]
else:
domain += [('company_id', '=', self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id)]
#don't take into account location that are production, supplier or inventory
res = []
offset = 0
while quantity > 0:
@ -578,10 +569,6 @@ class stock_quant(osv.osv):
order = 'in_date desc, id desc'
return self._quants_get_order(cr, uid, location, product, quantity, domain, order, context=context)
def _location_owner(self, cr, uid, quant, location, context=None):
''' Return the company owning the location if any '''
return location and (location.usage == 'internal') and location.company_id or False
def _check_location(self, cr, uid, location, context=None):
if location.usage == 'view':
raise osv.except_osv(_('Error'), _('You cannot move to a location of type view %s.') % (location.name))
@ -678,21 +665,19 @@ class stock_picking(osv.osv):
'''
res = {}
for pick in self.browse(cr, uid, ids, context=context):
cr.execute("select state, partially_available from stock_move where picking_id = %s", (pick.id,))
move_lines = cr.fetchall() #x[0] = state, x[1] partially available
if (not move_lines) or any([x[0] == 'draft' for x in move_lines]):
if (not pick.move_lines) or any([x.state == 'draft' for x in pick.move_lines]):
res[pick.id] = 'draft'
continue
if all([x[0] == 'cancel' for x in move_lines]):
if all([x.state == 'cancel' for x in pick.move_lines]):
res[pick.id] = 'cancel'
continue
if all([x[0] in ('cancel', 'done') for x in move_lines]):
if all([x.state in ('cancel', 'done') for x in pick.move_lines]):
res[pick.id] = 'done'
continue
order = {'confirmed': 0, 'waiting': 1, 'assigned': 2}
order_inv = {0: 'confirmed', 1: 'waiting', 2: 'assigned'}
lst = [order[x[0]] for x in move_lines if x[0] not in ('cancel', 'done')]
lst = [order[x.state] for x in pick.move_lines if x.state not in ('cancel', 'done')]
if pick.move_type == 'one':
res[pick.id] = order_inv[min(lst)]
else:
@ -702,8 +687,8 @@ class stock_picking(osv.osv):
res[pick.id] = order_inv[max(lst)]
if not all(x == 2 for x in lst):
#if all moves aren't assigned, check if we have one product partially available
for move in move_lines:
if move[1]:
for move in pick.move_lines:
if move.partially_available:
res[pick.id] = 'partially_available'
break
return res
@ -957,6 +942,7 @@ class stock_picking(osv.osv):
"""
# Try to find as much as possible top-level packages that can be moved
pack_obj = self.pool.get("stock.quant.package")
quant_obj = self.pool.get("stock.quant")
top_lvl_packages = set()
quants_to_compare = quants_suggested_locations.keys()
for pack in list(set([x.package_id for x in quants_suggested_locations.keys() if x and x.package_id])):
@ -965,9 +951,9 @@ class stock_picking(osv.osv):
good_pack = False
pack_destination = False
while loop:
pack_quants = pack_obj.get_contents(cr, uid, test_pack, context=context)
pack_quants = pack_obj.get_content(cr, uid, [test_pack.id], context=context)
all_in = True
for quant in pack_quants:
for quant in quant_obj.browse(cr, uid, pack_quants, context=context):
# If the quant is not in the quants to compare and not in the common location
if not quant in quants_to_compare:
all_in = False
@ -1030,13 +1016,14 @@ class stock_picking(osv.osv):
top_lvl_packages = self._get_top_level_packages(cr, uid, quants_suggested_locations, context=context)
# and then create pack operations for the top-level packages found
for pack in top_lvl_packages:
pack_quants = pack_obj.get_contents(cr, uid, pack, context=context)
pack_quants_ids = pack_obj.get_content(cr, uid, [pack.id], context=context)
pack_quants = quant_obj.browse(cr, uid, pack_quant_ids, context=context)
vals.append({
'picking_id': picking.id,
'package_id': pack.id,
'product_qty': 1.0,
'location_id': pack.location_id.id,
'location_dest_id': quants_suggested_locations[pack_quants[0]],
'location_dest_id': quants_suggested_locations[pack_quants[0]], context=context)],
})
#remove the quants inside the package so that they are excluded from the rest of the computation
for quant in pack_quants:
@ -1076,12 +1063,12 @@ class stock_picking(osv.osv):
})
return vals
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
context = context or {}
pack_operation_obj = self.pool.get('stock.pack.operation')
#used to avoid recomputing the remaining quantities at each new pack operation created
ctx = context.copy()
ctx['no_recompute'] = True
pack_operation_obj = self.pool.get('stock.pack.operation')
#get list of existing operations and delete them
existing_package_ids = pack_operation_obj.search(cr, uid, [('picking_id', 'in', picking_ids)], context=context)
@ -1102,11 +1089,11 @@ class stock_picking(osv.osv):
if forced_qties.get(move.product_id):
forced_qties[move.product_id] += forced_qty
else:
forced_qties[move.product_id] = forced_qty
for vals in self._prepare_pack_ops(cr, uid, picking, picking_quants, forced_qties, context=context):
pack_operation_obj.create(cr, uid, vals, context=context)
pack_operation_obj.create(cr, uid, vals, context=ctx)
#recompute the remaining quantities all at once
self.do_recompute_remaining_quantities(cr, uid, picking_ids, context=context)
def do_unreserve(self, cr, uid, picking_ids, context=None):
"""
@ -1140,8 +1127,8 @@ class stock_picking(osv.osv):
def _check_quants_reserved(ops):
if ops.package_id and not ops.product_id:
qty_op_rem[ops.id] = {}
package_obj.get_contents(cr, uid, ops.package_id)
for quant in package_obj.get_contents(cr, uid, ops.package_id):
quant_ids = package_obj.get_content(cr, uid, [ops.package_id.id], context=context)
for quant in quant_obj.browse(cr, uid, quant_ids, context=context):
if quant.id in quants_done.keys() and (quants_done[quant.id] == quant.qty):
#Entire packages means entire quants from those packages
if not quants_done.get(quant.id):
@ -1230,7 +1217,6 @@ class stock_picking(osv.osv):
quants_reserve_ok = all([quants_done[x] == 0 for x in quants_done.keys()])
return (quants_reserve_ok, remaining_qty_ok)
def do_recompute_remaining_quantities(self, cr, uid, picking_ids, context=None):
quants_res = True
remaining_res = True
@ -1241,9 +1227,6 @@ class stock_picking(osv.osv):
remaining_res = remaining_res and remaining_ok
return (quants_res, remaining_res)
def _create_extra_moves(self, cr, uid, picking, context=None):
'''This function creates move lines on a picking, at the time of do_transfer, based on
unexpected product transfers (or exceeding quantities) found in the pack operations.
@ -1277,7 +1260,6 @@ class stock_picking(osv.osv):
stock_move_obj.do_unreserve(cr, uid, move_ids, context=context)
stock_move_obj.action_assign(cr, uid, move_ids, context=context)
def do_transfer(self, cr, uid, picking_ids, context=None):
"""
If no pack operation, we do simple action_done of the picking
@ -1609,7 +1591,7 @@ class stock_move(osv.osv):
"* Waiting Availability: This state is reached when the procurement resolution is not straight forward. It may need the scheduler to run, a component to me manufactured...\n"\
"* Available: When products are reserved, it is set to \'Available\'.\n"\
"* Done: When the shipment is processed, the state is \'Done\'."),
'partially_available': fields.boolean('Partially Available', readonly = True, help = "Checks if the move has some stock reserved"),
'partially_available': fields.boolean('Partially Available', readonly=True, help="Checks if the move has some stock reserved"),
'price_unit': fields.float('Unit Price', help="Technical field used to record the product cost set by the user during a picking confirmation (when costing method used is 'average price' or 'real'). Value given in company currency and in product uom."), # as it's a technical field, we intentionally don't provide the digits attribute
'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
@ -1679,6 +1661,18 @@ class stock_move(osv.osv):
'propagate': True,
}
def _check_uom(self, cr, uid, ids, context=None):
for move in self.browse(cr, uid, ids, context=context):
if move.product_id.uom_id.category_id.id != move.product_uom.category_id.id:
return False
return True
_constraints = [
(_check_uom,
'You try to move a product using a UoM that is not compatible with the UoM of the product moved. Please use an UoM in the same UoM category.',
['product_uom']),
]
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
@ -1748,7 +1742,6 @@ class stock_move(osv.osv):
push_obj._apply(cr, uid, rule, move, context=context)
return True
def _create_procurement(self, cr, uid, move, context=None):
""" This will create a procurement order """
return self.pool.get("procurement.order").create(cr, uid, self._prepare_procurement_from_move(cr, uid, move, context=context))
@ -1761,17 +1754,6 @@ class stock_move(osv.osv):
# Check that we do not modify a stock.move which is done
frozen_fields = set(['product_qty', 'product_uom', 'product_uos_qty', 'product_uos', 'location_id', 'location_dest_id', 'product_id'])
for move in self.browse(cr, uid, ids, context=context):
#Check UoM in meantime
if vals.get('product_uom') or vals.get('product_id'):
product_uom = move.product_id.uom_id
move_uom = move.product_uom
if vals.get('product_uom'):
move_uom = self.pool.get('product.uom').browse(cr, uid, vals['product_uom'], context=context)
if vals.get('product_id'):
product_uom = self.pool.get('product.product').browse(cr, uid, vals['product_id'], context=context).uom_id
if move_uom.category_id.id != product_uom.category_id.id:
raise osv.except_osv(_('Operation Forbidden'),
_('Category of Product UoM must be the same as the category of the UoM of the move'))
if move.state == 'done':
if frozen_fields.intersection(vals):
raise osv.except_osv(_('Operation Forbidden!'),
@ -2113,11 +2095,11 @@ class stock_move(osv.osv):
self.write(cr, uid, [move.move_dest_id.id], {'state': 'confirmed'}, context=context)
return self.write(cr, uid, ids, {'state': 'cancel', 'move_dest_id': False}, context=context)
def _check_package_from_moves(self, cr, uid, moves, context=None):
def _check_package_from_moves(self, cr, uid, ids, context=None):
pack_obj = self.pool.get("stock.quant.package")
packs = set()
for move in moves:
packs |= set([q.package_id for q in move.quant_ids if q.package_id and q.qty > 0])
for move in self.browse(cr, uid, ids, context=context):
packs |= set([q.package_id.id for q in move.quant_ids if q.package_id and q.qty > 0])
return pack_obj._check_location_constraint(cr, uid, list(packs), context=context)
def action_done(self, cr, uid, ids, context=None):
@ -2140,7 +2122,6 @@ class stock_move(osv.osv):
for link in move.linked_move_operation_ids:
operations.add(link.operation_id)
#Sort operations according to entire packages first, then package + lot, package only, lot only
operations = list(operations)
operations.sort(key = lambda x: ((x.package_id and not x.product_id) and -4 or 0) + (x.package_id and -2 or 0) + (x.lot_id and -1 or 0))
@ -2157,16 +2138,20 @@ class stock_move(osv.osv):
dom = main_domain + self.pool.get('stock.move.operation.link').get_specific_domain(cr, uid, record, context=context)
quants = quant_obj.quants_get_prefered_domain(cr, uid, ops.location_id, move.product_id, record.qty, domain=dom, prefered_domain=prefered_domain,
fallback_domain=fallback_domain, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
package_id = False
if not ops.product_id and ops.package_id:
#if a package and a result_package is given, we will put package_id, otherwise it will be result_pakege
#but for operations having only result_package_id, we will create new quants in the final package directly
package_id = ops.package_id.id
if ops.result_package_id.id:
#if a result package is given, all quants go there
quant_dest_package_id = ops.result_package_id.id
elif ops.product_id and ops.package_id:
#if a package and a product is given, we will remove quants from the pack.
quant_dest_package_id = False
else:
package_id = ops.result_package_id.id
quant_obj.quants_move(cr, uid, quants, move, ops.location_dest_id, lot_id=ops.lot_id.id, owner_id=ops.owner_id.id, src_package_id=ops.package_id.id, dest_package_id=package_id, context=context)
#otherwise we keep the current pack of the quant, which may mean None
quant_dest_package_id = ops.package_id.id
quant_obj.quants_move(cr, uid, quants, move, ops.location_dest_id, lot_id=ops.lot_id.id, owner_id=ops.owner_id.id, src_package_id=ops.package_id.id, dest_package_id=quant_dest_package_id, context=context)
# Handle pack in pack
pack_op_obj.process_packaging(cr, uid, ops, context=context)
if not ops.product_id and ops.package_id and ops.result_package_id.id != ops.package_id.parent_id.id:
pack_obj.write(cr, SUPERUSER_ID, [ops.package_id.id], {'result_package_id': ops.result_package_id.id}, context=context)
move_qty[move.id] -= record.qty
#Check for remaining qtys and unreserve/check move_dest_id in
for move in self.browse(cr, uid, ids, context=context):
@ -2192,7 +2177,7 @@ class stock_move(osv.osv):
procurement_ids.append(move.procurement_id.id)
# Check the packages have been placed in the correct locations
self._check_package_from_moves(cr, uid, self.browse(cr, uid, ids, context=context), context=context)
self._check_package_from_moves(cr, uid, ids, context=context)
# Apply on picking
done_date = context.get('force_date', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
self.write(cr, uid, ids, {'state': 'done', 'date': done_date}, context=context)
@ -3469,16 +3454,18 @@ class stock_package(osv.osv):
'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').get(cr, uid, 'stock.quant.package') or _('Unknown Pack')
}
def _check_location_constraint(self, cr, uid, packs, context=None):
def _check_location_constraint(self, cr, uid, ids, context=None):
'''checks that all quants in a package are stored in the same location. This function cannot be used
as a constraint because it needs to be checked on pack operations (they may not call write on the
package)
'''
for pack in packs:
quant_obj = self.pool.get('stock.quant')
for pack in self.browse(cr, uid, ids, context=context):
parent = pack
while parent.parent_id:
parent = parent.parent_id
quants = self.get_contents(cr, uid, parent, context=context)
quant_ids = self.get_content(cr, uid, [parent.id], context=context)
quants = quant_obj.browse(cr, uid, quant_ids, context=context)
location_id = quants and quants[0].location_id.id or False
if not all([quant.location_id.id == location_id for quant in quants if quant.qty > 0]):
raise osv.except_osv(_('Error'), _('Everything inside a package should be in the same location'))
@ -3513,17 +3500,6 @@ class stock_package(osv.osv):
child_package_ids = self.search(cr, uid, [('id', 'child_of', ids)], context=context)
return self.pool.get('stock.quant').search(cr, uid, [('package_id', 'in', child_package_ids)], context=context)
def get_contents(self, cr, uid, pack, context=None):
quants = pack.quant_ids
children_ids = pack.children_ids
while children_ids:
children2_ids = []
for child in children_ids:
quants += child.quant_ids
children2_ids += child.children_ids
children_ids = children2_ids
return quants
def get_content_package(self, cr, uid, ids, context=None):
quants_ids = self.get_content(cr, uid, ids, context=context)
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'stock', 'quantsact', context=context)
@ -3587,7 +3563,6 @@ class stock_pack_operation(osv.osv):
res[record.move_id.product_id.id] -= record.qty
return res
def _get_remaining_qty(self, cr, uid, ids, name, args, context=None):
uom_obj = self.pool.get('product.uom')
res = {}
@ -3666,12 +3641,8 @@ class stock_pack_operation(osv.osv):
if isinstance(ids, (int, long)):
ids = [ids]
if not context.get("no_recompute"):
if vals.get('picking_id'):
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, [vals['picking_id']], context=context)
else:
moves = self.browse(cr, uid, ids, context=context)
pickings = list(set([x.picking_id.id for x in moves]))
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, pickings, context=context)
pickings = vals.get('picking_id') and [vals['picking_id]] or list(set([x.picking_id.id for x in self.browse(cr, uid, ids, context=context)]))
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, pickings, context=context)
return res
def create(self, cr, uid, vals, context=None):
@ -3680,17 +3651,6 @@ class stock_pack_operation(osv.osv):
if vals.get("picking_id") and not context.get("no_recompute"):
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, [vals['picking_id']], context=context)
return res_id
def process_packaging(self, cr, uid, operation, context=None):
''' Process the packaging of a given operation, after the quants have been moved. If there was not enough quants found
a quant already has been with the good package information so we don't consider that case in this method'''
pack_obj = self.pool.get("stock.quant.package")
if not operation.product_id and operation.package_id and operation.result_package_id.id != operation.package_id.parent_id.id:
pack_obj.write(cr, SUPERUSER_ID, [operation.package_id.id], {'result_package_id': operation.result_package_id.id}, context=context)
#TODO: this function can be refactored
def _search_and_increment(self, cr, uid, picking_id, domain, context=None):

View File

@ -77,33 +77,35 @@ class stock_quant(osv.osv):
if quant.product_id.cost_method == 'real' and quant.location_id.usage != 'internal':
self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
"""
Accounting Valuation Entries
quants: Quants to create accounting valuation entries for
move: Move to use
"""
def _account_entry_move(self, cr, uid, quants, move, context=None):
location_from = move.location_id
location_to = quants[0].location_id
"""
Accounting Valuation Entries
quants: browse record list of Quants to create accounting valuation entries for. Unempty and all quants are supposed to have the same location id (thay already moved in)
move: Move to use. browse record
"""
if context is None:
context = {}
if quants[0].product_id.valuation != 'real_time':
return False
if quants[0].owner_id:
#if the quant isn't owned by the company, we don't make any valuation entry
return False
if quants[0].qty <= 0:
#we don't make any stock valuation for negative quants because the valuation is already made for the counterpart.
#At that time the valuation will be made at the product cost price and afterward there will be new accounting entries
#to make the adjustments when we know the real cost price.
return False
company_from = self._location_owner(cr, uid, quants[0], location_from, context=context)
company_to = self._location_owner(cr, uid, quants[0], location_to, context=context)
location_obj = self.pool.get('stock.location')
location_from = move.location_id
location_to = quants[0].location_id
company_from = location_obj._location_owner(cr, uid, location_from, context=context)
company_to = location_obj._location_owner(cr, uid, location_to, context=context)
if company_from == company_to:
return False
if move.product_id.valuation != 'real_time':
return False
for q in quants:
if q.owner_id:
#if the quant isn't owned by the company, we don't make any valuation entry
return False
if q.qty <= 0:
#we don't make any stock valuation for negative quants because the valuation is already made for the counterpart.
#At that time the valuation will be made at the product cost price and afterward there will be new accounting entries
#to make the adjustments when we know the real cost price.
return False
# Create Journal Entry for products arriving in the company
if company_to:
ctx = context.copy()
@ -126,19 +128,17 @@ class stock_quant(osv.osv):
else:
self._create_account_move_line(cr, uid, quants, move, acc_valuation, acc_dest, journal_id, context=ctx)
def _quant_create(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, force_location=False, context=None):
quant = super(stock_quant, self)._quant_create(cr, uid, qty, move, lot_id, owner_id, src_package_id, dest_package_id, force_location, context=context)
if move.product_id.valuation == 'real_time':
self._account_entry_move(cr, uid, [quant], move, context)
return quant
def move_single_quant_tuples(self, cr, uid, quants, move, location_dest_id, dest_package_id, context=None):
quant_record = super(stock_quant, self).move_single_quant_tuples(cr, uid, quants, move, location_dest_id, dest_package_id, context=context)
def move_quants_write(self, cr, uid, quants, move, location_dest_id, dest_package_id, context=None):
res = super(stock_quant, self).move_quants_write(cr, uid, quants, move, location_dest_id, dest_package_id, context=context)
if move.product_id.valuation == 'real_time':
quants_filt = [x[0] for x in quants]
self._account_entry_move(cr, uid, quants_filt, move, context=context)
return quant_record
self._account_entry_move(cr, uid, quants, move, context=context)
return res
def _get_accounting_data_for_valuation(self, cr, uid, move, context=None):
@ -190,7 +190,6 @@ class stock_quant(osv.osv):
#the company currency... so we need to use round() before creating the accounting entries.
valuation_amount = currency_obj.round(cr, uid, move.company_id.currency_id, valuation_amount * qty)
partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
debit_line_vals = {
'name': move.name,
'product_id': move.product_id.id,
@ -219,20 +218,18 @@ class stock_quant(osv.osv):
def _create_account_move_line(self, cr, uid, quants, move, credit_account_id, debit_account_id, journal_id, context=None):
#group quants by cost
quant_cost = {}
quant_cost_qty = {}
for quant in quants:
if quant_cost.get(quant.cost):
if quant_cost_qty.get(quant.cost):
quant_cost_qty[quant.cost] += quant.qty
else:
quant_cost[quant.cost] = quant
quant_cost_qty[quant.cost] = quant.qty
move_obj = self.pool.get('account.move')
for cost in quant_cost_qty.keys():
move_lines = self._prepare_account_move_line(cr, uid, move, quant_cost_qty[cost], cost, credit_account_id, debit_account_id, context=context)
for cost, qty in quant_cost_qty.items():
move_lines = self._prepare_account_move_line(cr, uid, move, qty, cost, credit_account_id, debit_account_id, context=context)
return move_obj.create(cr, uid, {'journal_id': journal_id,
'line_id': move_lines,
'perdiod_id': self.pool.get('account.period').find(cr, uid, move.date, context=context)[0],
'period_id': self.pool.get('account.period').find(cr, uid, move.date, context=context)[0],
'date': move.date,
'ref': move.picking_id and move.picking_id.name}, context=context)