[MERGE] merge from perf3 until merge
bzr revid: jco@openerp.com-20140304161944-hbb58wtdj2e4c2u7
This commit is contained in:
commit
0a9bf2fe25
|
@ -100,7 +100,7 @@ class mail_message(osv.Model):
|
|||
def _get_to_read(self, cr, uid, ids, name, arg, context=None):
|
||||
""" Compute if the message is unread by the current user. """
|
||||
res = dict((id, False) for id in ids)
|
||||
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, uid, [
|
||||
('partner_id', 'in', [partner_id]),
|
||||
|
@ -119,7 +119,7 @@ class mail_message(osv.Model):
|
|||
def _get_starred(self, cr, uid, ids, name, arg, context=None):
|
||||
""" Compute if the message is unread by the current user. """
|
||||
res = dict((id, False) for id in ids)
|
||||
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, uid, [
|
||||
('partner_id', 'in', [partner_id]),
|
||||
|
@ -208,7 +208,7 @@ class mail_message(osv.Model):
|
|||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||
|
||||
def _get_default_author(self, cr, uid, context=None):
|
||||
return self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
return self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
|
||||
_defaults = {
|
||||
'type': 'email',
|
||||
|
@ -266,7 +266,7 @@ class mail_message(osv.Model):
|
|||
:return number of message mark as read
|
||||
"""
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
user_pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
user_pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)]
|
||||
if not create_missing:
|
||||
domain += [('read', '=', not read)]
|
||||
|
@ -294,7 +294,7 @@ class mail_message(osv.Model):
|
|||
(i.e. when acting on displayed messages not notified)
|
||||
"""
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
user_pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
user_pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)]
|
||||
if not create_missing:
|
||||
domain += [('starred', '=', not starred)]
|
||||
|
@ -332,7 +332,7 @@ class mail_message(osv.Model):
|
|||
"""
|
||||
res_partner_obj = self.pool.get('res.partner')
|
||||
ir_attachment_obj = self.pool.get('ir.attachment')
|
||||
pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
|
||||
# 1. Aggregate partners (author_id and partner_ids) and attachments
|
||||
partner_ids = set()
|
||||
|
@ -653,7 +653,7 @@ class mail_message(osv.Model):
|
|||
elif not ids:
|
||||
return ids
|
||||
|
||||
pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
|
||||
pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
author_ids, partner_ids, allowed_ids = set([]), set([]), set([])
|
||||
model_ids = {}
|
||||
|
||||
|
@ -714,7 +714,7 @@ class mail_message(osv.Model):
|
|||
ids = [ids]
|
||||
not_obj = self.pool.get('mail.notification')
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
|
||||
# Read mail_message.ids to have their values
|
||||
message_values = dict.fromkeys(ids, {})
|
||||
|
|
|
@ -286,7 +286,7 @@ class mail_thread(osv.AbstractModel):
|
|||
res = []
|
||||
for field, operator, value in args:
|
||||
assert field == name
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
if (operator == '=' and value) or (operator == '!=' and not value): # is a follower
|
||||
res_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
|
||||
else: # is not a follower or unknown domain
|
||||
|
@ -354,7 +354,7 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
# subscribe uid unless asked not to
|
||||
if not context.get('mail_create_nosubscribe'):
|
||||
pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid).partner_id.id
|
||||
pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
message_follower_ids = values.get('message_follower_ids') or [] # webclient can send None or False
|
||||
message_follower_ids.append([4, pid])
|
||||
values['message_follower_ids'] = message_follower_ids
|
||||
|
@ -1586,7 +1586,7 @@ class mail_thread(osv.AbstractModel):
|
|||
mail_followers_obj = self.pool.get('mail.followers')
|
||||
subtype_obj = self.pool.get('mail.message.subtype')
|
||||
|
||||
user_pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
user_pid = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
if set(partner_ids) == set([user_pid]):
|
||||
try:
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
|
@ -1776,7 +1776,7 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
def message_mark_as_unread(self, cr, uid, ids, context=None):
|
||||
""" Set as unread. """
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
cr.execute('''
|
||||
UPDATE mail_notification SET
|
||||
read=false
|
||||
|
@ -1788,7 +1788,7 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
def message_mark_as_read(self, cr, uid, ids, context=None):
|
||||
""" Set as read. """
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, SUPERUSER_ID, [uid], ['partner_id'], context=context)[0]['partner_id'][0]
|
||||
cr.execute('''
|
||||
UPDATE mail_notification SET
|
||||
read=true
|
||||
|
|
|
@ -159,6 +159,7 @@ class product_uom(osv.osv):
|
|||
('factor_gt_zero', 'CHECK (factor!=0)', 'The conversion ratio for a unit of measure cannot be 0!')
|
||||
]
|
||||
|
||||
|
||||
def _compute_qty(self, cr, uid, from_uom_id, qty, to_uom_id=False, round=True):
|
||||
if not from_uom_id or not qty or not to_uom_id:
|
||||
return qty
|
||||
|
@ -807,7 +808,10 @@ class product_product(osv.osv):
|
|||
|
||||
result = []
|
||||
for product in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
sellers = filter(lambda x: x.name.id == partner_id, product.seller_ids)
|
||||
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 = {
|
||||
|
|
|
@ -31,6 +31,7 @@ import openerp.addons.decimal_precision as dp
|
|||
from openerp.osv.orm import browse_record, browse_null
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP
|
||||
|
||||
|
||||
class purchase_order(osv.osv):
|
||||
|
||||
def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
|
||||
|
@ -155,12 +156,19 @@ class purchase_order(osv.osv):
|
|||
|
||||
def _get_picking_ids(self, cr, uid, ids, field_names, args, context=None):
|
||||
res = {}
|
||||
for purchase_id in ids:
|
||||
picking_ids = set()
|
||||
move_ids = self.pool.get('stock.move').search(cr, uid, [('purchase_line_id.order_id', '=', purchase_id)], context=context)
|
||||
for move in self.pool.get('stock.move').browse(cr, uid, move_ids, context=context):
|
||||
picking_ids.add(move.picking_id.id)
|
||||
res[purchase_id] = list(picking_ids)
|
||||
query = """
|
||||
SELECT picking_id, po.id FROM stock_picking p, stock_move m, purchase_order_line pol, purchase_order po
|
||||
WHERE po.id in %s and po.id = pol.order_id and pol.id = m.purchase_line_id and m.picking_id = p.id
|
||||
GROUP BY picking_id, po.id
|
||||
|
||||
"""
|
||||
cr.execute(query, (tuple(ids), ))
|
||||
picks = cr.fetchall()
|
||||
for pick in picks:
|
||||
if not res.get(pick[1]):
|
||||
res[pick[1]] = [pick[0]]
|
||||
else:
|
||||
res[pick[1]].append(pick[0])
|
||||
return res
|
||||
|
||||
STATE_SELECTION = [
|
||||
|
|
|
@ -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:
|
||||
if 'state' in vals and vals['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
|
||||
|
@ -71,7 +71,7 @@ class stock_picking(osv.osv):
|
|||
def _get_picking_to_recompute(self, cr, uid, ids, context=None):
|
||||
picking_ids = set()
|
||||
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
|
||||
if move.picking_id:
|
||||
if move.picking_id and move.purchase_line_id:
|
||||
picking_ids.add(move.picking_id.id)
|
||||
return list(picking_ids)
|
||||
|
||||
|
@ -79,7 +79,6 @@ class stock_picking(osv.osv):
|
|||
'reception_to_invoice': fields.function(_get_to_invoice, type='boolean', string='Invoiceable on incoming shipment?',
|
||||
help='Does the picking contains some moves related to a purchase order invoiceable on the reception?',
|
||||
store={
|
||||
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 10),
|
||||
'stock.move': (_get_picking_to_recompute, ['purchase_line_id', 'picking_id'], 10),
|
||||
}),
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
I duplicate order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.copy(cr, uid, ref('purchase_order_1'), context)
|
||||
self.copy_data(cr, uid, ref('purchase_order_1'), context)
|
|
@ -676,6 +676,8 @@ class sale_order(osv.osv):
|
|||
|
||||
:return: True
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
sale_line_obj = self.pool.get('sale.order.line')
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -701,7 +703,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
|
||||
procurement_obj.run(cr, uid, proc_ids, context=context)
|
||||
ctx = context.copy()
|
||||
ctx["no_picking_assign"] = True
|
||||
procurement_obj.run(cr, uid, proc_ids, context=ctx)
|
||||
#Check all moves associated and do the picking_assign
|
||||
procurement_obj.group_picking_assign(cr, uid, proc_ids, context=context)
|
||||
|
||||
#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':
|
||||
|
@ -1170,3 +1176,5 @@ class procurement_order(osv.osv):
|
|||
'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'),
|
||||
}
|
||||
|
||||
def group_picking_assign(self, cr, uid, proc_ids, context=None):
|
||||
return True
|
||||
|
|
|
@ -67,7 +67,7 @@ class sale_order(osv.osv):
|
|||
def _get_orders_procurements(self, cr, uid, ids, context=None):
|
||||
res = set()
|
||||
for proc in self.pool.get('procurement.order').browse(cr, uid, ids, context=context):
|
||||
if proc.sale_line_id:
|
||||
if proc.state =='done' and proc.sale_line_id:
|
||||
res.add(proc.sale_line_id.order_id.id)
|
||||
return list(res)
|
||||
|
||||
|
@ -102,7 +102,6 @@ class sale_order(osv.osv):
|
|||
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
|
||||
help="""On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""),
|
||||
'shipped': fields.function(_get_shipped, string='Delivered', type='boolean', store={
|
||||
'stock.move': (_get_orders, ['state'], 10),
|
||||
'procurement.order': (_get_orders_procurements, ['state'], 10)
|
||||
}),
|
||||
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
|
||||
|
@ -454,3 +453,18 @@ class stock_picking(osv.osv):
|
|||
created_lines = sale_line_obj.invoice_line_create(cr, uid, sale_line_ids, context=context)
|
||||
invoice_line_obj.write(cr, uid, created_lines, {'invoice_id': invoice_id}, context=context)
|
||||
return invoice_id
|
||||
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
_inherit = 'procurement.order'
|
||||
|
||||
def group_picking_assign(self, cr, uid, proc_ids, context=None):
|
||||
moves = []
|
||||
procurements = proc_ids
|
||||
while procurements:
|
||||
related_moves = []
|
||||
for proc in self.browse(cr, uid, procurements, context=context):
|
||||
related_moves += proc.move_ids
|
||||
procurements = self.search(cr, uid, [('move_dest_id', 'in', [x.id for x in related_moves])], context=context)
|
||||
moves += related_moves
|
||||
self.pool.get("stock.move")._group_picking_assign(cr, uid, moves, context=context)
|
||||
|
|
|
@ -95,7 +95,7 @@ class procurement_rule(osv.osv):
|
|||
class procurement_order(osv.osv):
|
||||
_inherit = "procurement.order"
|
||||
_columns = {
|
||||
'location_id': fields.many2one('stock.location', 'Procurement Location'), # not required because task may create procurements that aren't linked to a location with project_mrp
|
||||
'location_id': fields.many2one('stock.location', 'Procurement Location'), # not required because task may create procurements that aren't linked to a location with project_mrp
|
||||
'move_ids': fields.one2many('stock.move', 'procurement_id', 'Moves', help="Moves created by the procurement"),
|
||||
'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Move which caused (created) the procurement"),
|
||||
'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Preferred Routes', help="Preferred route to be followed by the procurement order. Usually copied from the generating document (SO) but could be set up manually."),
|
||||
|
|
|
@ -30,9 +30,9 @@ from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FO
|
|||
from openerp import SUPERUSER_ID
|
||||
import openerp.addons.decimal_precision as dp
|
||||
import logging
|
||||
from profilehooks import profile
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Incoterms
|
||||
#----------------------------------------------------------
|
||||
|
@ -321,6 +321,8 @@ class stock_quant(osv.osv):
|
|||
move.refresh()
|
||||
if move.reserved_availability == move.product_qty and move.state in ('confirmed', 'waiting'):
|
||||
self.pool.get('stock.move').write(cr, uid, [move.id], {'state': 'assigned'}, context=context)
|
||||
elif move.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, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, location_dest_id = False, context=None):
|
||||
"""Moves all given stock.quant in the destination location of the given move.
|
||||
|
@ -358,7 +360,8 @@ class stock_quant(osv.osv):
|
|||
#if the quant we are moving had been split and was inside a package, it means we unpacked it
|
||||
if new_quant and new_quant.package_id:
|
||||
vals['package_id'] = False
|
||||
self.write(cr, SUPERUSER_ID, [quant.id], vals, context=context)
|
||||
if self._check_location(cr, uid, location_to, context):
|
||||
self.write(cr, SUPERUSER_ID, [quant.id], vals, context=context)
|
||||
quant.refresh()
|
||||
return new_quant
|
||||
|
||||
|
@ -536,6 +539,8 @@ class stock_quant(osv.osv):
|
|||
|
||||
def quants_unreserve(self, cr, uid, move, context=None):
|
||||
related_quants = [x.id for x in move.reserved_quant_ids]
|
||||
if related_quants and move.partially_available:
|
||||
self.pool.get("stock.move").write(cr, uid, [move.id], {'partially_available': False}, context=context)
|
||||
return self.write(cr, SUPERUSER_ID, related_quants, {'reservation_id': False, 'link_move_operation_id': False}, context=context)
|
||||
|
||||
def _quants_get_order(self, cr, uid, location, product, quantity, domain=[], orderby='in_date', context=None):
|
||||
|
@ -577,16 +582,11 @@ class stock_quant(osv.osv):
|
|||
''' 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, ids, context=None):
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
if record.location_id.usage == 'view':
|
||||
raise osv.except_osv(_('Error'), _('You cannot move product %s to a location of type view %s.') % (record.product_id.name, record.location_id.name))
|
||||
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))
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_location, 'You cannot move products to a location of the type view.', ['location_id'])
|
||||
]
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Stock Picking
|
||||
|
@ -644,19 +644,21 @@ class stock_picking(osv.osv):
|
|||
'''
|
||||
res = {}
|
||||
for pick in self.browse(cr, uid, ids, context=context):
|
||||
if (not pick.move_lines) or any([x.state == 'draft' for x in pick.move_lines]):
|
||||
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]):
|
||||
res[pick.id] = 'draft'
|
||||
continue
|
||||
if all([x.state == 'cancel' for x in pick.move_lines]):
|
||||
if all([x[0] == 'cancel' for x in move_lines]):
|
||||
res[pick.id] = 'cancel'
|
||||
continue
|
||||
if all([x.state in ('cancel', 'done') for x in pick.move_lines]):
|
||||
if all([x[0] in ('cancel', 'done') for x in 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.state] for x in pick.move_lines if x.state not in ('cancel', 'done')]
|
||||
lst = [order[x[0]] for x in move_lines if x[0] not in ('cancel', 'done')]
|
||||
if pick.move_type == 'one':
|
||||
res[pick.id] = order_inv[min(lst)]
|
||||
else:
|
||||
|
@ -666,24 +668,17 @@ 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 pick.move_lines:
|
||||
if move.reserved_quant_ids:
|
||||
for move in move_lines:
|
||||
if move[1]:
|
||||
res[pick.id] = 'partially_available'
|
||||
break
|
||||
return res
|
||||
|
||||
def _get_pickings(self, cr, uid, ids, context=None):
|
||||
res = set()
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.picking_id:
|
||||
res.add(move.picking_id.id)
|
||||
return list(res)
|
||||
|
||||
def _get_pickings_from_quant(self, cr, uid, ids, context=None):
|
||||
res = set()
|
||||
for quant in self.browse(cr, uid, ids, context=context):
|
||||
if quant.reservation_id and quant.reservation_id.picking_id:
|
||||
res.add(quant.reservation_id.picking_id.id)
|
||||
for move in self.read(cr, uid, ids, ['picking_id'], context=context):
|
||||
if move['picking_id']:
|
||||
res.add(move['picking_id'][0])
|
||||
return list(res)
|
||||
|
||||
def _get_pack_operation_exist(self, cr, uid, ids, field_name, arg, context=None):
|
||||
|
@ -716,9 +711,8 @@ class stock_picking(osv.osv):
|
|||
'note': fields.text('Notes', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
|
||||
'move_type': fields.selection([('direct', 'Partial'), ('one', 'All at once')], 'Delivery Method', required=True, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="It specifies goods to be deliver partially or all at once"),
|
||||
'state': fields.function(_state_get, type="selection", store={
|
||||
'stock.picking': (lambda self, cr, uid, ids, ctx: ids, ['move_type', 'move_lines'], 20),
|
||||
'stock.move': (_get_pickings, ['state', 'picking_id'], 20),
|
||||
'stock.quant': (_get_pickings_from_quant, ['reservation_id'], 20)}, selection=[
|
||||
'stock.picking': (lambda self, cr, uid, ids, ctx: ids, ['move_type'], 20),
|
||||
'stock.move': (_get_pickings, ['state', 'picking_id', 'partially_available'], 20)}, selection=[
|
||||
('draft', 'Draft'),
|
||||
('cancel', 'Cancelled'),
|
||||
('waiting', 'Waiting Another Operation'),
|
||||
|
@ -737,9 +731,9 @@ class stock_picking(osv.osv):
|
|||
),
|
||||
'priority': fields.selection([('0', 'Low'), ('1', 'Normal'), ('2', 'High')], states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, string='Priority', required=True),
|
||||
'min_date': fields.function(get_min_max_date, multi="min_max_date", fnct_inv=_set_min_date,
|
||||
store={'stock.move': (_get_pickings, ['state', 'date_expected'], 20)}, type='datetime', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, string='Scheduled Date', select=1, help="Scheduled time for the first part of the shipment to be processed. Setting manually a value here would set it as expected date for all the stock moves.", track_visibility='onchange'),
|
||||
store={'stock.move': (_get_pickings, ['date_expected'], 20)}, type='datetime', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, string='Scheduled Date', select=1, help="Scheduled time for the first part of the shipment to be processed. Setting manually a value here would set it as expected date for all the stock moves.", track_visibility='onchange'),
|
||||
'max_date': fields.function(get_min_max_date, multi="min_max_date",
|
||||
store={'stock.move': (_get_pickings, ['state', 'date_expected'], 20)}, type='datetime', string='Max. Expected Date', select=2, help="Scheduled time for the last part of the shipment to be processed"),
|
||||
store={'stock.move': (_get_pickings, ['date_expected'], 20)}, type='datetime', string='Max. Expected Date', select=2, help="Scheduled time for the last part of the shipment to be processed"),
|
||||
'date': fields.datetime('Commitment Date', help="Date promised for the completion of the transfer order, usually set the time of the order and revised later on.", select=True, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, track_visibility='onchange'),
|
||||
'date_done': fields.datetime('Date of Transfer', help="Date of Completion", states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
|
||||
'move_lines': fields.one2many('stock.move', 'picking_id', 'Internal Moves', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
|
||||
|
@ -846,8 +840,6 @@ class stock_picking(osv.osv):
|
|||
for pick in self.browse(cr, uid, ids, context=context):
|
||||
move_ids = [x.id for x in pick.move_lines if x.state in ['confirmed', 'waiting']]
|
||||
self.pool.get('stock.move').force_assign(cr, uid, move_ids, context=context)
|
||||
if pick.pack_operation_exist:
|
||||
self.do_prepare_partial(cr, uid, [pick.id], context=None)
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
|
@ -1110,10 +1102,12 @@ class stock_picking(osv.osv):
|
|||
|
||||
def do_recompute_remaining_quantities(self, cr, uid, picking_ids, context=None):
|
||||
pack_op_obj = self.pool.get('stock.pack.operation')
|
||||
quants_res = True
|
||||
for picking in self.browse(cr, uid, picking_ids, context=context):
|
||||
op_ids = [op.id for op in picking.pack_operation_ids]
|
||||
if op_ids:
|
||||
pack_op_obj.recompute_rem_qty_from_operation(cr, uid, op_ids, context=context)
|
||||
quants_res = quants_res and pack_op_obj.recompute_rem_qty_from_operation(cr, uid, op_ids, context=context)
|
||||
return quants_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
|
||||
|
@ -1161,28 +1155,34 @@ class stock_picking(osv.osv):
|
|||
self.action_done(cr, uid, [picking.id], context=context)
|
||||
continue
|
||||
else:
|
||||
self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
|
||||
quants_ok = self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
|
||||
#create extra moves in the picking (unexpected product moves coming from pack operations)
|
||||
self._create_extra_moves(cr, uid, picking, context=context)
|
||||
if not quants_ok:
|
||||
self._create_extra_moves(cr, uid, picking, context=context)
|
||||
picking.refresh()
|
||||
#split move lines eventually
|
||||
todo_move_ids = []
|
||||
toassign_move_ids = []
|
||||
no_rereserve = True
|
||||
for move in picking.move_lines:
|
||||
remaining_qty = move.remaining_qty
|
||||
if move.state in ('done', 'cancel'):
|
||||
#ignore stock moves cancelled or already done
|
||||
continue
|
||||
elif move.state == 'draft':
|
||||
toassign_move_ids.append(move.id)
|
||||
if move.remaining_qty == 0:
|
||||
no_rereserve = False
|
||||
if remaining_qty == 0:
|
||||
if move.state in ('draft', 'assigned', 'confirmed'):
|
||||
todo_move_ids.append(move.id)
|
||||
elif move.remaining_qty > 0 and move.remaining_qty < move.product_qty:
|
||||
new_move = stock_move_obj.split(cr, uid, move, move.remaining_qty, context=context)
|
||||
elif remaining_qty > 0 and remaining_qty < move.product_qty:
|
||||
no_rereserve = False
|
||||
new_move = stock_move_obj.split(cr, uid, move, remaining_qty, context=context)
|
||||
todo_move_ids.append(move.id)
|
||||
#Assign move as it was assigned before
|
||||
toassign_move_ids.append(new_move)
|
||||
self.rereserve_quants(cr, uid, picking, move_ids=todo_move_ids, context=context)
|
||||
if not quants_ok or not no_rereserve:
|
||||
self.rereserve_quants(cr, uid, picking, move_ids=todo_move_ids, context=context)
|
||||
if todo_move_ids and not context.get('do_only_split'):
|
||||
self.pool.get('stock.move').action_done(cr, uid, todo_move_ids, context=context)
|
||||
elif context.get('do_only_split'):
|
||||
|
@ -1339,7 +1339,7 @@ class stock_move(osv.osv):
|
|||
uom_obj = self.pool.get('product.uom')
|
||||
res = {}
|
||||
for m in self.browse(cr, uid, ids, context=context):
|
||||
res[m.id] = uom_obj._compute_qty_obj(cr, uid, m.product_uom, m.product_uom_qty, m.product_id.uom_id, round=False)
|
||||
res[m.id] = uom_obj._compute_qty_obj(cr, uid, m.product_uom, m.product_uom_qty, m.product_id.uom_id, round=False, context=context)
|
||||
return res
|
||||
|
||||
def _get_remaining_qty(self, cr, uid, ids, field_name, args, context=None):
|
||||
|
@ -1350,7 +1350,7 @@ class stock_move(osv.osv):
|
|||
for record in move.linked_move_operation_ids:
|
||||
qty -= record.qty
|
||||
#converting the remaining quantity in the move UoM
|
||||
res[move.id] = uom_obj._compute_qty(cr, uid, move.product_id.uom_id.id, qty, move.product_uom.id)
|
||||
res[move.id] = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, qty, move.product_uom, round=False, context=context)
|
||||
return res
|
||||
|
||||
def _get_lot_ids(self, cr, uid, ids, field_name, args, context=None):
|
||||
|
@ -1386,7 +1386,7 @@ class stock_move(osv.osv):
|
|||
res[move.id] = '' # 'not applicable' or 'n/a' could work too
|
||||
continue
|
||||
total_available = min(move.product_qty, move.reserved_availability + move.availability)
|
||||
total_available = uom_obj._compute_qty(cr, uid, move.product_id.uom_id.id, total_available, move.product_uom.id)
|
||||
total_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, total_available, move.product_uom, context=context)
|
||||
info = str(total_available)
|
||||
#look in the settings if we need to display the UoM name or not
|
||||
config_ids = settings_obj.search(cr, uid, [], limit=1, order='id DESC', context=context)
|
||||
|
@ -1397,7 +1397,7 @@ class stock_move(osv.osv):
|
|||
if move.reserved_availability:
|
||||
if move.reserved_availability != total_available:
|
||||
#some of the available quantity is assigned and some are available but not reserved
|
||||
reserved_available = uom_obj._compute_qty(cr, uid, move.product_id.uom_id.id, move.reserved_availability, move.product_uom.id)
|
||||
reserved_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, move.reserved_availability, move.product_uom, context=context)
|
||||
info += _(' (%s reserved)') % str(reserved_available)
|
||||
else:
|
||||
#all available quantity is assigned
|
||||
|
@ -1424,6 +1424,7 @@ class stock_move(osv.osv):
|
|||
res += [x.id for x in picking.move_lines]
|
||||
return res
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Description', required=True, select=True),
|
||||
'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'),
|
||||
|
@ -1432,7 +1433,7 @@ class stock_move(osv.osv):
|
|||
'date_expected': fields.datetime('Expected 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)]}),
|
||||
# TODO: improve store to add dependency on product UoM
|
||||
'product_qty': fields.function(_quantity_normalize, type='float', store=True, string='Quantity',
|
||||
'product_qty': fields.function(_quantity_normalize, type='float', store={'stock.move': (lambda self, cr, uid, ids, ctx: ids, ['product_uom_qty', 'product_uom'], 20)}, string='Quantity',
|
||||
digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
help='Quantity in the default UoM of the product'),
|
||||
'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
|
@ -1476,7 +1477,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"),
|
||||
'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),
|
||||
|
@ -1546,16 +1547,6 @@ 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:
|
||||
|
@ -1640,6 +1631,17 @@ 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!'),
|
||||
|
@ -1789,6 +1791,10 @@ class stock_move(osv.osv):
|
|||
return {'value': result}
|
||||
|
||||
def _picking_assign(self, cr, uid, move, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
if context.get("no_picking_assign") and context['no_picking_assign']:
|
||||
return False
|
||||
if move.picking_id or not move.picking_type_id:
|
||||
return False
|
||||
context = context or {}
|
||||
|
@ -1814,6 +1820,40 @@ class stock_move(osv.osv):
|
|||
move.write({'picking_id': pick})
|
||||
return True
|
||||
|
||||
def _group_picking_assign(self, cr, uid, moves, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
if context.get("no_picking_assign") and context['no_picking_assign']:
|
||||
return False
|
||||
move_dict = {}
|
||||
for move in moves:
|
||||
group_by = (move.location_id, move.location_dest_id, move.group_id)
|
||||
if not move_dict.get(group_by, False):
|
||||
move_dict[group_by] = [move]
|
||||
else:
|
||||
move_dict[group_by].append(move)
|
||||
pick_obj = self.pool.get("stock.picking")
|
||||
for to_compare in move_dict.keys():
|
||||
picks = pick_obj.search(cr, uid, [
|
||||
('group_id', '=', to_compare[2].id),
|
||||
('location_id', '=', to_compare[0].id),
|
||||
('location_dest_id', '=', to_compare[1].id),
|
||||
('state', 'in', ['draft', 'confirmed', 'waiting']),
|
||||
], context=context)
|
||||
if picks:
|
||||
pick = picks[0]
|
||||
else:
|
||||
move = move_dict[to_compare][0]
|
||||
values = {
|
||||
'origin': move.origin,
|
||||
'company_id': move.company_id and move.company_id.id or False,
|
||||
'move_type': move.group_id and move.group_id.move_type or 'one',
|
||||
'partner_id': move.group_id and move.group_id.partner_id and move.group_id.partner_id.id or False,
|
||||
'picking_type_id': move.picking_type_id and move.picking_type_id.id or False,
|
||||
}
|
||||
pick = pick_obj.create(cr, uid, values, context=context)
|
||||
self.write(cr, uid, [x.id for x in move_dict[to_compare]], {'picking_id': pick}, context=context)
|
||||
|
||||
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
|
||||
|
@ -1982,6 +2022,7 @@ class stock_move(osv.osv):
|
|||
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)
|
||||
|
||||
@profile(immediate=True)
|
||||
def action_done(self, cr, uid, ids, context=None):
|
||||
""" Process completly the moves given as ids and if all moves are done, it will finish the picking.
|
||||
"""
|
||||
|
@ -2002,6 +2043,7 @@ 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))
|
||||
|
@ -2035,7 +2077,10 @@ class stock_move(osv.osv):
|
|||
fallback_domain = [('reservation_id', '=', False)]
|
||||
self.check_tracking(cr, uid, move, move.restrict_lot_id.id, context=context)
|
||||
qty = move_qty[move.id]
|
||||
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, 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)
|
||||
if move.location_id.usage in ('supplier', 'inventory', 'production'):
|
||||
quants = [(None, move.product_uom_qty)]
|
||||
else:
|
||||
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, 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)
|
||||
quant_obj.quants_move(cr, uid, quants, move, lot_id=move.restrict_lot_id.id, owner_id=move.restrict_partner_id.id, context=context)
|
||||
#unreserve the quants and make them available for other operations/moves
|
||||
quant_obj.quants_unreserve(cr, uid, move, context=context)
|
||||
|
@ -2139,7 +2184,7 @@ class stock_move(osv.osv):
|
|||
uom_obj = self.pool.get('product.uom')
|
||||
context = context or {}
|
||||
|
||||
uom_qty = uom_obj._compute_qty(cr, uid, move.product_id.uom_id.id, qty, move.product_uom.id)
|
||||
uom_qty = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, qty, move.product_uom)
|
||||
uos_qty = uom_qty * move.product_uos_qty / move.product_uom_qty
|
||||
|
||||
defaults = {
|
||||
|
@ -3250,9 +3295,9 @@ class stock_package(osv.osv):
|
|||
def _get_packages(self, cr, uid, ids, context=None):
|
||||
"""Returns packages from quants for store"""
|
||||
res = set()
|
||||
for quant in self.browse(cr, uid, ids, context=context):
|
||||
if quant.package_id:
|
||||
res.add(quant.package_id.id)
|
||||
for quant in self.read(cr, uid, ids, ['package_id'], context=context):
|
||||
if quant['package_id']:
|
||||
res.add(quant['package_id'][0])
|
||||
return list(res)
|
||||
|
||||
def _get_packages_to_relocate(self, cr, uid, ids, context=None):
|
||||
|
@ -3417,6 +3462,15 @@ class stock_pack_operation(osv.osv):
|
|||
res[record.move_id.product_id.id] -= record.qty
|
||||
return res
|
||||
|
||||
def _get_remaining_qty_product_uom(self, cr, uid, ops, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
qty = ops.product_qty
|
||||
if ops.product_uom_id:
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_uom_id, ops.product_qty, ops.product_id.uom_id, context=context)
|
||||
for record in ops.linked_move_operation_ids:
|
||||
qty -= record.qty
|
||||
return qty
|
||||
|
||||
def _get_remaining_qty(self, cr, uid, ids, name, args, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
res = {}
|
||||
|
@ -3429,12 +3483,12 @@ class stock_pack_operation(osv.osv):
|
|||
else:
|
||||
qty = ops.product_qty
|
||||
if ops.product_uom_id:
|
||||
qty = uom_obj._compute_qty(cr, uid, ops.product_uom_id.id, ops.product_qty, ops.product_id.uom_id.id)
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_uom_id, ops.product_qty, ops.product_id.uom_id, context=context)
|
||||
for record in ops.linked_move_operation_ids:
|
||||
qty -= record.qty
|
||||
#converting the remaining quantity in the pack operation UoM
|
||||
if ops.product_uom_id:
|
||||
qty = uom_obj._compute_qty(cr, uid, ops.product_id.uom_id.id, qty, ops.product_uom_id.id)
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_id.uom_id, qty, ops.product_uom_id, context=context)
|
||||
res[ops.id] = qty
|
||||
return res
|
||||
|
||||
|
@ -3506,10 +3560,12 @@ class stock_pack_operation(osv.osv):
|
|||
qty_to_assign = qty
|
||||
for move in sorted_moves:
|
||||
if move.product_id.id == product_id and move.state not in ['done', 'cancel']:
|
||||
qty_on_link = min(move.remaining_qty, qty_to_assign)
|
||||
link_obj.create(cr, uid, {'move_id': move.id, 'operation_id': op.id, 'qty': qty_on_link}, context=context)
|
||||
qty_on_link = min(qty_move_rem[move.id], qty_to_assign)
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (move.id, op.id, qty_on_link,))
|
||||
qty_move_rem[move.id] -= qty_on_link
|
||||
# link_obj.create(cr, uid, {'move_id': move.id, 'operation_id': op.id, 'qty': qty_on_link}, context=context)
|
||||
qty_to_assign -= qty_on_link
|
||||
move.refresh()
|
||||
if qty_to_assign <= 0:
|
||||
break
|
||||
|
||||
|
@ -3521,8 +3577,9 @@ class stock_pack_operation(osv.osv):
|
|||
if not quants_done.get(quant.id):
|
||||
quants_done[quant.id] = 0
|
||||
link_obj.create(cr, uid, {'move_id': quant.reservation_id.id, 'operation_id': ops.id, 'qty': quant.qty}, context=context)
|
||||
qty_move_rem[quant.reservation_id.id] -= quant.qty
|
||||
else:
|
||||
qty = uom_obj._compute_qty(cr, uid, ops.product_uom_id.id, ops.product_qty, ops.product_id.uom_id.id)
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_uom_id, ops.product_qty, ops.product_id.uom_id, context=context)
|
||||
#Check moves with same product
|
||||
for move in [x for x in ops.picking_id.move_lines if ops.product_id.id == x.product_id.id]:
|
||||
for quant in move.reserved_quant_ids:
|
||||
|
@ -3548,6 +3605,7 @@ class stock_pack_operation(osv.osv):
|
|||
quants_done[quant.id] = 0
|
||||
qty -= qty_todo
|
||||
link_obj.create(cr, uid, {'move_id': quant.reservation_id.id, 'operation_id': ops.id, 'qty': qty_todo}, context=context)
|
||||
qty_move_rem[quant.reservation_id.id] -= qty_todo
|
||||
|
||||
link_obj = self.pool.get('stock.move.operation.link')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
|
@ -3555,32 +3613,42 @@ class stock_pack_operation(osv.osv):
|
|||
quant_obj = self.pool.get('stock.quant')
|
||||
quants_done = {}
|
||||
|
||||
qty_rem = {}
|
||||
qty_move_rem = {}
|
||||
operations = self.browse(cr, uid, op_ids, context=context)
|
||||
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))
|
||||
sorted_moves = []
|
||||
for op in operations:
|
||||
if not sorted_moves:
|
||||
#sort moves in order to process first the ones that have already reserved quants
|
||||
for move in op.picking_id.move_lines:
|
||||
prod_qty = move.product_qty
|
||||
qty_rem[move.id] = prod_qty - move.reserved_availability
|
||||
qty_move_rem[move.id] = prod_qty
|
||||
sorted_moves = op.picking_id.move_lines
|
||||
sorted_moves.sort(key=lambda x: x.product_qty - x.reserved_availability)
|
||||
sorted_moves.sort(key=lambda x: qty_rem[x.id])
|
||||
|
||||
to_unlink_ids = [x.id for x in op.linked_move_operation_ids]
|
||||
if to_unlink_ids:
|
||||
link_obj.unlink(cr, uid, to_unlink_ids, context=context)
|
||||
_check_quants_reserved(op)
|
||||
|
||||
quants_reserve_ok = True
|
||||
for op in operations:
|
||||
op.refresh()
|
||||
if op.product_id:
|
||||
#TODO: Remaining qty: UoM conversions are done twice
|
||||
normalized_qty = uom_obj._compute_qty(cr, uid, op.product_uom_id.id, op.remaining_qty, op.product_id.uom_id.id)
|
||||
normalized_qty = self._get_remaining_qty_product_uom(cr, uid, op, context)
|
||||
if normalized_qty > 0:
|
||||
quants_reserve_ok = False
|
||||
_create_link_for_product(op.product_id.id, normalized_qty)
|
||||
elif op.package_id:
|
||||
prod_quants = self._get_remaining_prod_quantities(cr, uid, op, context=context)
|
||||
for product_id, qty in prod_quants.items():
|
||||
if qty > 0:
|
||||
quants_reserve_ok = False
|
||||
_create_link_for_product(product_id, qty)
|
||||
return quants_reserve_ok
|
||||
|
||||
def process_packaging(self, cr, uid, operation, quants, context=None):
|
||||
''' Process the packaging of a given operation, after the quants have been moved. If there was not enough quants found
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,47 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Dropshipping Module',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'summary': 'Dropshipping',
|
||||
'description': """
|
||||
Manage sales quotations and stock locations
|
||||
==========================================
|
||||
|
||||
This adds the route to make dropshipping sales orders in which the product sold are directly transfered from the reseller to the customer (direct delivery) without creating any internal document for the transfer.
|
||||
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'images': [],
|
||||
'depends': ['stock_dropshipping'],
|
||||
'init_xml': [],
|
||||
'data': [],
|
||||
'demo_xml': [],
|
||||
'test': [
|
||||
'test/megatestmtobuy.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,286 @@
|
|||
-
|
||||
I first create a warehouse with pick-pack-ship and reception in 2 steps
|
||||
-
|
||||
!record {model: stock.warehouse, id: mwh_pps}:
|
||||
name: Mega WareHouse PickPackShip
|
||||
code: mwhpps
|
||||
reception_steps: 'two_steps'
|
||||
delivery_steps: 'pick_pack_ship'
|
||||
-
|
||||
Next I create a new product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto}:
|
||||
name: "My Product"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 1
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto2}:
|
||||
name: "My Product 2"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 2
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto3}:
|
||||
name: "My Product 3"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 4
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mts}:
|
||||
name: "My Product MTS"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 2
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
Set routes on product to be MTO and Buy
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
route_warehouse0_buy = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock.warehouse0')).buy_pull_id.route_id.id
|
||||
route_warehouse0_mto = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock.warehouse0')).mto_pull_id.route_id.id
|
||||
self.write(cr, uid, [ref('mprod_mto'), ref('mprod_mto2'), ref('mprod_mto3')], { 'route_ids': [(6, 0, [route_warehouse0_mto,route_warehouse0_buy])]}, context=context)
|
||||
-
|
||||
Create a sales order with 36 lines.
|
||||
-
|
||||
!record {model: sale.order, id: sale_order_product_mto2}:
|
||||
partner_id: base.res_partner_3
|
||||
note: Create Sales order
|
||||
warehouse_id: mwh_pps
|
||||
order_line:
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 99.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
-
|
||||
Confirm the sale order
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_order_product_mto2}
|
||||
-
|
||||
Check sales order is confirmed
|
||||
-
|
||||
!python {model: sale.order}:
|
||||
print self.browse(cr, uid, ref('sale_order_product_mto2')).state
|
||||
-
|
||||
Create a sales order with 36 lines.
|
||||
-
|
||||
!record {model: sale.order, id: sale_order_product_mto3}:
|
||||
partner_id: base.res_partner_3
|
||||
note: Create Sales order
|
||||
warehouse_id: mwh_pps
|
||||
order_line:
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
route_id: stock_dropshipping.route_drop_shipping
|
||||
-
|
||||
Confirm the sale order
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_order_product_mto3}
|
||||
-
|
||||
Check sales order is confirmed
|
||||
-
|
||||
!python {model: sale.order}:
|
||||
print self.browse(cr, uid, ref('sale_order_product_mto3')).state
|
||||
-
|
||||
Confirm all purchase orders that are in draft related
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
po_ids = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2')), ('state', '=', 'draft')])
|
||||
self.signal_purchase_confirm(cr, uid, po_ids)
|
||||
-
|
||||
Doing all incoming shipments
|
||||
-
|
||||
!python {model: purchase.order.line}: |
|
||||
import time
|
||||
beforebefore = time.time()
|
||||
print time.time()
|
||||
prod_list = [ref('mprod_mto'), ref('mprod_mto2'), ref('mprod_mto3'), ref('mprod_mts')]
|
||||
po_line_ids = self.search(cr, uid, [('product_id', 'in', prod_list)])
|
||||
# Search all related moves
|
||||
move_obj = self.pool.get("stock.move")
|
||||
related_moves = move_obj.search(cr, uid, [('purchase_line_id', 'in', po_line_ids)])
|
||||
moves = move_obj.browse(cr, uid, related_moves)
|
||||
related_pickings = [x.picking_id for x in moves]
|
||||
pickings = list(set(related_pickings))
|
||||
op_obj = self.pool.get('stock.pack.operation')
|
||||
pack_obj = self.pool.get('stock.quant.package')
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
# Process those pickings and put in boxes of 20 pieces
|
||||
for pick in pickings:
|
||||
pick_obj.do_prepare_partial(cr, uid, [pick.id])
|
||||
#for ops in pick.pack_operation_ids:
|
||||
# pick
|
||||
# while ops.product_qty > 100:
|
||||
# op_obj.write(cr, uid, [ops.id], {'product_qty': ops.product_qty - 100})
|
||||
# pack_id = pack_obj.create(cr, uid, {}, context=context)
|
||||
# op_obj.copy(cr, uid, ops.id, {'product_qty': 100, 'result_package_id': pack_id})
|
||||
# print "copy"
|
||||
# ops.refresh()
|
||||
print "moves", len(pick.move_lines), "pack_ops", len(pick.pack_operation_ids), time.time()
|
||||
pick.refresh()
|
||||
pick_obj.do_transfer(cr, uid, [pick.id])
|
||||
print "Done transfer", time.time()
|
||||
print "totaltime", time.time() - beforebefore
|
||||
#Search all dests of moves
|
||||
move_dest_ids = [x.move_dest_id for x in moves]
|
||||
move_dest_ids = list(set(move_dest_ids))
|
||||
related_dest_pickings = [x.picking_id for x in move_dest_ids if x.picking_id]
|
||||
picks = list(set(related_dest_pickings))
|
||||
print "picks", picks
|
||||
for pick in picks:
|
||||
pick_obj.do_prepare_partial(cr, uid, [pick.id])
|
||||
pick_obj.do_transfer(cr, uid, [pick.id])
|
||||
print "after second transfer", time.time()
|
||||
move_dest_ids = [x.move_dest_id.move_dest_id for x in moves if x.move_dest_id]
|
||||
move_dest_ids = list(set(move_dest_ids))
|
||||
related_dest_pickings = [x.picking_id for x in move_dest_ids if x.picking_id]
|
||||
picks = list(set(related_dest_pickings))
|
||||
print "picks", picks
|
||||
for pick in picks:
|
||||
pick_obj.do_prepare_partial(cr, uid, [pick.id])
|
||||
pick_obj.do_transfer(cr, uid, [pick.id])
|
||||
print "after third transfer", time.time()
|
|
@ -0,0 +1,203 @@
|
|||
-
|
||||
I first create a warehouse with pick-pack-ship and reception in 2 steps
|
||||
-
|
||||
!record {model: stock.warehouse, id: mwh_pps}:
|
||||
name: Mega WareHouse Simple
|
||||
code: mwhpps
|
||||
-
|
||||
Next I create a new product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto}:
|
||||
name: "My Product"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 1
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto2}:
|
||||
name: "My Product 2"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 2
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mto3}:
|
||||
name: "My Product 3"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 4
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
I will create another product in this warehouse
|
||||
-
|
||||
!record {model: product.product, id: mprod_mts}:
|
||||
name: "My Product MTS"
|
||||
type: product
|
||||
uom_id: product.product_uom_unit
|
||||
uom_po_id: product.product_uom_unit
|
||||
seller_ids:
|
||||
- delay: 2
|
||||
name: base.res_partner_2
|
||||
min_qty: 2.0
|
||||
qty: 10.0
|
||||
-
|
||||
Set routes on product to be MTO and Buy
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
route_warehouse0_buy = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock.warehouse0')).buy_pull_id.route_id.id
|
||||
route_warehouse0_mto = self.pool.get('stock.warehouse').browse(cr, uid, ref('stock.warehouse0')).mto_pull_id.route_id.id
|
||||
self.write(cr, uid, [ref('mprod_mto'), ref('mprod_mto2'), ref('mprod_mto3')], { 'route_ids': [(6, 0, [route_warehouse0_mto,route_warehouse0_buy])]}, context=context)
|
||||
-
|
||||
Create a sales order with 36 lines.
|
||||
-
|
||||
!record {model: sale.order, id: sale_order_product_mto2}:
|
||||
partner_id: base.res_partner_3
|
||||
note: Create Sales order
|
||||
warehouse_id: mwh_pps
|
||||
order_line:
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 99.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mts
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto3
|
||||
product_uom_qty: 67.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 500.00
|
||||
- product_id: mprod_mto
|
||||
product_uom_qty: 100.00
|
||||
- product_id: mprod_mto2
|
||||
product_uom_qty: 67.00
|
||||
-
|
||||
Confirm the sale order
|
||||
-
|
||||
!workflow {model: sale.order, action: order_confirm, ref: sale_order_product_mto2}
|
||||
-
|
||||
Check sales order is confirmed
|
||||
-
|
||||
!python {model: sale.order}:
|
||||
print self.browse(cr, uid, ref('sale_order_product_mto2')).state
|
||||
-
|
||||
Confirm all purchase orders that are in draft related
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
po_ids = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2')), ('state', '=', 'draft')])
|
||||
self.signal_purchase_confirm(cr, uid, po_ids)
|
||||
-
|
||||
Doing all incoming shipments
|
||||
-
|
||||
!python {model: purchase.order.line}: |
|
||||
import time
|
||||
beforebefore = time.time()
|
||||
print time.time()
|
||||
prod_list = [ref('mprod_mto'), ref('mprod_mto2'), ref('mprod_mto3'), ref('mprod_mts')]
|
||||
po_line_ids = self.search(cr, uid, [('product_id', 'in', prod_list)])
|
||||
# Search all related moves
|
||||
move_obj = self.pool.get("stock.move")
|
||||
related_moves = move_obj.search(cr, uid, [('purchase_line_id', 'in', po_line_ids)])
|
||||
moves = move_obj.browse(cr, uid, related_moves)
|
||||
related_pickings = [x.picking_id for x in moves]
|
||||
pickings = list(set(related_pickings))
|
||||
op_obj = self.pool.get('stock.pack.operation')
|
||||
pack_obj = self.pool.get('stock.quant.package')
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
# Process those pickings and put in boxes of 20 pieces
|
||||
for pick in pickings:
|
||||
#pick_obj.do_prepare_partial(cr, uid, [pick.id])
|
||||
#for ops in pick.pack_operation_ids:
|
||||
# pick
|
||||
# while ops.product_qty > 100:
|
||||
# op_obj.write(cr, uid, [ops.id], {'product_qty': ops.product_qty - 100})
|
||||
# pack_id = pack_obj.create(cr, uid, {}, context=context)
|
||||
# op_obj.copy(cr, uid, ops.id, {'product_qty': 100, 'result_package_id': pack_id})
|
||||
# print "copy"
|
||||
# ops.refresh()
|
||||
print "moves", len(pick.move_lines), "pack_ops", len(pick.pack_operation_ids), time.time()
|
||||
pick.refresh()
|
||||
pick_obj.do_transfer(cr, uid, [pick.id])
|
||||
print "Done transfer", time.time()
|
||||
print "totaltime", time.time() - beforebefore
|
||||
#Search all dests of moves
|
||||
move_dest_ids = [x.move_dest_id for x in moves]
|
||||
move_dest_ids = list(set(move_dest_ids))
|
||||
related_dest_pickings = [x.picking_id for x in move_dest_ids if x.picking_id]
|
||||
picks = list(set(related_dest_pickings))
|
||||
for pick in picks:
|
||||
pick_obj.do_prepare_partial(cr, uid, [pick.id])
|
||||
pick_obj.do_transfer(cr, uid, [pick.id])
|
||||
print "after second transfer", time.time()
|
Loading…
Reference in New Issue