OK, so I am answering my own question. I have ended up doing it my defining 
'group' moves which combine other moves. The other moves stay around, but the 
group moves appear on the order and picking. When the group move is complete, 
it knows to complete the other moves also.

Here is an attempt at a patch. It will operate as before, but if you tick 
'full_merge' (the default) it will also merge lines.

Comments from the code:

+# this merges purchase orders which are to the same partner and location
+# if full_merge is enabled, then it will also merge order lines for the same 
product, location, etc.
+# The original code tried to do this but since each line had a different stock 
move it didn't work
+# This code creates a new 'group' stock move for each one that it wants to 
merge. This group move
+# will then appear on the purchase order and picking, so that orders look 
correct, and reception picking
+# is easier.
+# At the end when the picking is complete, the code (elsewhere) knows to look 
inside the group and
+# process the grouped moves as well.
+#
+# Additions required:
+#   New fields in stock.move
+#      - group            True if a group (i.e. not a real item, but created 
from 2 or more others)
+#      - move_group_id    ID of the group move for this item, if this is a 
member of a group
+#
+#  so members of the group will have move_group_id non-null, and group False
+# the group itself will have move_group_id null, and 'group' True
+#
+# Also added a 'group' field to the order line, so that the user can see that 
the line is a group
+# However there is no way to see what was grouped, since order lines don't let 
the user link back to 




Index: bin/addons/stock/stock.py
===================================================================
--- bin/addons/stock/stock.py   (revision 666)
+++ bin/addons/stock/stock.py   (working copy)
@@ -484,6 +484,7 @@
       self.write(cr,uid, ids, 
{'state':'done'})
       return True
 
+   # this moves 'assigned' items in a picking to 'done'. This is 
their final resting place
    def action_move(self, cr, uid, ids, 
context={}):
       for pick in self.browse(cr, uid, 
ids):
          todo = []
@@ -742,6 +743,8 @@
       'tracking_id': 
fields.many2one('stock.tracking', 'Tracking lot', select=True, 
help="Tracking lot is the code that will be put on the logistic 
unit/pallet"),
       'lot_id': fields.many2one('stock.lot', 
'Consumer lot', select=True, readonly=True),
 
+      'move_group_id': 
fields.many2one('stock.move', 'Grouped move', help = "Allows a number of 
moves to be grouped so they show as one on orders and pickings. This records 
the group that this move is in"),
+      'group':fields.boolean('Group', 
readonly=True, select=True, help = "true if this stock move is a group of other 
moves"),
       'move_dest_id': 
fields.many2one('stock.move', 'Dest. Move'),
       'move_history_ids': 
fields.many2many('stock.move', 'stock_move_history_ids', 'parent_id', 
'child_id', 'Move History'),
       'move_history_ids2': 
fields.many2many('stock.move', 'stock_move_history_ids', 'child_id', 
'parent_id', 'Move History'),
@@ -749,7 +752,9 @@
 
       'note': fields.text('Notes'),
 
-      'state': 
fields.selection([('draft','Draft'),('waiting','Waiting'),('confirmed','Confirmed'),('assigned','Assigned'),('done','Done'),('cancel','cancel')],
 'State', readonly=True, select=True),
+      # grouped means that this move is grouped into 
another, so shouldn't be used by itself until the group disbands
+      # group means this is a group, containing other 
moves. It should generally be ignored as it is not a real stock move
+      'state': 
fields.selection([('draft','Draft'),('waiting','Waiting'),('confirmed','Confirmed'),('grouped','Grouped'),('group','Group'),('assigned','Assigned'),('done','Done'),('cancel','cancel')],
 'State', readonly=True, select=True),
       'price_unit': fields.float('Unit Price',
          digits=(16, 
int(config['price_accuracy']))),
    }
@@ -870,19 +875,44 @@
       return True
 
    def action_done(self, cr, uid, ids, 
context=None):
+      
+      # this function closes off a stock move, mark it as 
assigned (or group, for a group move)
+      def process_done (dest):
+         mid = dest.id
+         if dest.id:
+            cr.execute('insert 
into stock_move_history_ids (parent_id,child_id) values 
(%d,%d)', (move.id, dest.id))
+         if dest.state in 
('waiting','confirmed','grouped'):
+            # update the state
+            self.write(cr, uid, 
[dest.id], dest.group and {'state':'group'} or 
{'state':'assigned'})
+            
+            # if there is an attached 
picking list, give it a kick, as we may now have all the items it needs to 
complete
+            if dest.picking_id:
+               wf_service = 
netsvc.LocalService("workflow")
+              
 wf_service.trg_write(uid, 'stock.picking', dest.picking_id.id, cr)
+            #else:
+            #   pass
+               # 
self.action_done(cr, uid, [move.move_dest_id.id])
+
       for move in self.browse(cr, uid, 
ids):
-         if move.move_dest_id.id and 
(move.state != 'done'):
-            mid = move.move_dest_id.id
-            if 
move.move_dest_id.id:
-              
 cr.execute('insert into stock_move_history_ids 
(parent_id,child_id) values (%d,%d)', (move.id, 
move.move_dest_id.id))
-            if move.move_dest_id.state 
in ('waiting','confirmed'):
-              
 self.write(cr, uid, [move.move_dest_id.id], 
{'state':'assigned'})
-               if 
move.move_dest_id.picking_id:
-                 
 wf_service = netsvc.LocalService("workflow")
-                 
 wf_service.trg_write(uid, 'stock.picking', 
move.move_dest_id.picking_id.id, cr)
-               else:
-                 
 pass
-                 
 # self.action_done(cr, uid, [move.move_dest_id.id])
+         dest = move.move_dest_id
+         if dest.id and (move.state != 
'done'):
+            
+            # mark this move as 
assigned
+            process_done (dest)
+            
+            # if this move is a group, 
mark its memebers as assigned also
+            if dest.group:
+               # find the 
IDs of the members
+               item_ids = 
self.search(cr, uid, [('move_group_id', '=', dest.id)])
+               
+               # process 
each in turn
+               for item in 
self.browse (cr, uid, item_ids):
+                 
 process_done (item)
+                  
+               # handle the 
attached move, if any
+               # this will 
be currently set to 'waiting', so change it to 'group' so it is dead
+               if 
dest.move_dest_id.id:
+                 
 self.write(cr, uid, [dest.move_dest_id.id], 
{'state':'group'})
 
          #
          # Accounting Entries
Index: bin/addons/stock/stock_view.xml
===================================================================
--- bin/addons/stock/stock_view.xml   (revision 666)
+++ bin/addons/stock/stock_view.xml   (working copy)
@@ -500,6 +500,8 @@
                  
&nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<field>
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<field>
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<newline>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<label>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;<button>
@@ -751,6 +753,8 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<newline>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<field>
Index&#58; bin/addons/mrp/mrp.py
===================================================================
--- bin/addons/mrp/mrp.py&nbsp; &nbsp;&#40;revision 666&#41;
+++ bin/addons/mrp/mrp.py&nbsp; &nbsp;&#40;working copy&#41;
@@ -194,7 +194,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#40;_check_recursion, 'Error ! You can not 
create recursive BoM.', &#91;'parent_id'&#93;&#41;
&nbsp;&nbsp; &nbsp;&#93;
&nbsp;
-&nbsp; &nbsp;
+
&nbsp;&nbsp; &nbsp;def onchange_product_id&#40;self, cr, uid, ids, product_id, 
name, context=&#123;&#125;&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if product_id&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;prod=self.pool.get&#40;'product.product'&#41;.browse&#40;cr,uid,&#91;product_id&#93;&#41;&#91;0&#93;
@@ -291,7 +291,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'author_id'&#58; 
fields.many2one&#40;'res.users', 'Author'&#41;,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'bom_id'&#58; fields.many2one&#40;'mrp.bom', 
'BoM', select=True&#41;,
&nbsp;&nbsp; &nbsp;&#125;
-&nbsp; &nbsp;
+
&nbsp;&nbsp; &nbsp;_defaults = &#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'author_id'&#58; lambda x,y,z,c&#58; z,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'date'&#58; lambda *a&#58; 
time.strftime&#40;'%Y-%m-%d'&#41;,
@@ -533,6 +533,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move_id=False
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;newdate = 
production.date_planned
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
line.product_id.type in &#40;'product', 'consu'&#41;&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# create the 
move to the production location
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;res_dest_id = self.pool.get&#40;'stock.move'&#41;.create&#40;cr, uid, 
&#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'name'&#58;'PROD&#58;'+production.name,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'date_planned'&#58; production.date_planned,
@@ -545,6 +546,8 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'state'&#58; 'waiting',
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&#125;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;moves.append&#40;res_dest_id&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# create the 
move to itself for the procurement
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move_id 
= self.pool.get&#40;'stock.move'&#41;.create&#40;cr, uid, &#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'name'&#58;'PROD&#58;'+production.name,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'picking_id'&#58;picking_id,
@@ -568,9 +571,11 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'procure_method'&#58; line.product_id.procure_method,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'move_id'&#58; move_id, 
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#125;&#41;
+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # confirm the 
procurement automatically
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;wf_service = 
netsvc.LocalService&#40;"workflow"&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;wf_service.trg_validate&#40;uid, 'mrp.procurement', proc_id, 
'button_confirm', cr&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if toconfirm&#58;
+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # confirm the stock 
picking automatically
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;wf_service = 
netsvc.LocalService&#40;"workflow"&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;wf_service.trg_validate&#40;uid, 'stock.picking', picking_id, 
'button_confirm', cr&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;self.write&#40;cr, uid, 
&#91;production.id&#93;, &#123;'picking_id'&#58;picking_id, 'move_lines'&#58; 
&#91;&#40;6,0,moves&#41;&#93;, 'state'&#58;'confirmed'&#125;&#41;
Index&#58; bin/addons/purchase/wizard/wizard_group.py
===================================================================
--- bin/addons/purchase/wizard/wizard_group.py&nbsp; &nbsp;&#40;revision 
666&#41;
+++ bin/addons/purchase/wizard/wizard_group.py&nbsp; &nbsp;&#40;working 
copy&#41;
@@ -34,15 +34,42 @@
&nbsp;import pooler
&nbsp;from osv.orm import browse_record
&nbsp;
+
+# enhanced from original version by Simon Glass, Bluewater Systems Ltd, 
www.bluewatersys.com
+#
+# this merges purchase orders which are to the same partner and location
+# if full_merge is enabled, then it will also merge order lines for the same 
product, location, etc.
+# The original code tried to do this but since each line had a different stock 
move it didn't work
+# This code creates a new 'group' stock move for each one that it wants to 
merge. This group move
+# will then appear on the purchase order and picking, so that orders look 
correct, and reception picking
+# is easier.
+# At the end when the picking is complete, the code &#40;elsewhere&#41; knows 
to look inside the group and
+# process the grouped moves as well.
+#
+# Additions required&#58;
+#&nbsp; &nbsp;New fields in stock.move
+#&nbsp; &nbsp;&nbsp; &nbsp;- group&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;&nbsp; &nbsp;True if a group &#40;i.e. not a real item, but created from 
2 or more others&#41;
+#&nbsp; &nbsp;&nbsp; &nbsp;- move_group_id &nbsp; &nbsp;ID of the group move 
for this item, if this is a member of a group
+#
+#&nbsp; so members of the group will have move_group_id non-null, and group 
False
+# the group itself will have move_group_id null, and 'group' True
+#
+# Also added a 'group' field to the order line, so that the user can see that 
the line is a group
+# However there is no way to see what was grouped, since order lines don't let 
the user link back to 
+# the stock move
+
&nbsp;merge_form = """<xml>
&nbsp;<form>
&nbsp;&nbsp; &nbsp;<separator>
&nbsp;&nbsp; &nbsp;<newline>
&nbsp;&nbsp; &nbsp;<label>
+&nbsp; &nbsp;<newline>
+&nbsp; &nbsp;<field>
&nbsp;</form>
&nbsp;"""
&nbsp;
&nbsp;merge_fields = &#123;
+&nbsp; &nbsp;'full_merge'&#58; &#123;'string'&#58;'Merge order lines for the 
same product', 'type'&#58;'boolean', 'required'&#58;True, 'default' &#58; 
True&#125;,
&nbsp;&#125;
&nbsp;
&nbsp;ack_form = """<xml>
@@ -53,15 +80,30 @@
&nbsp;ack_fields = &#123;&#125;
&nbsp;
&nbsp;def _mergeOrders&#40;self, cr, uid, data, context&#41;&#58;
+&nbsp; &nbsp;# merge order lines also\
+&nbsp; &nbsp;full_merge = data &#91;'form'&#93; &#91;'full_merge'&#93;
&nbsp;&nbsp; &nbsp;order_obj = 
pooler.get_pool&#40;cr.dbname&#41;.get&#40;'purchase.order'&#41;
-
+&nbsp; &nbsp; 
+&nbsp; &nbsp; # patch to ensure that procurement is updated with new purchase 
order number
+&nbsp; &nbsp;proc_obj = 
pooler.get_pool&#40;cr.dbname&#41;.get&#40;'mrp.procurement'&#41;
+&nbsp; &nbsp;stockmove_obj = 
pooler.get_pool&#40;cr.dbname&#41;.get&#40;'stock.move'&#41;
+&nbsp; &nbsp; 
+&nbsp; &nbsp; # make a key out of a set of fields. We will use this to compare 
order lines, and merge those that have the same key
&nbsp;&nbsp; &nbsp;def make_key&#40;br, fields&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;list_key = &#91;&#93;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;for field in fields&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;field_val = getattr&#40;br, 
field&#41;
-&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if field in 
&#40;'product_id','move_dest_id', 'account_analytic_id'&#41;&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# for this, check the eventual location 
is the same, rather than the move id
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# &#40;since we can group the moves if 
needed&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if full_merge and field == 
'move_dest_id'&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;field_val = 
field_val.location_dest_id
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;field = 'move_dest_id_loc'
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;elif field in 
&#40;'product_id','move_dest_id', 'account_analytic_id'&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if not field_val&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;field_val = False
+
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# convert objects to a list of IDs
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if isinstance&#40;field_val, 
browse_record&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;field_val = 
field_val.id
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;elif isinstance&#40;field_val, 
list&#41;&#58;
@@ -69,7 +111,28 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;list_key.append&#40;&#40;field, 
field_val&#41;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;list_key.sort&#40;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return tuple&#40;list_key&#41;
-&nbsp; &nbsp;&nbsp; &nbsp;
+
+&nbsp; &nbsp;# get the salient details from an existing move into a dict
+&nbsp; &nbsp;def get_stock_move &#40;move_id&#41;&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;move = stockmove_obj.browse &#40;cr, uid, 
&#91;move_id&#93;&#41; &#91;0&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;return &#123;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'name'&#58; move.name,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'picking_id'&#58;move.picking_id.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'product_id'&#58; move.product_id.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'product_qty'&#58; move.product_qty,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'product_uom'&#58; move.product_uom.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'date_planned'&#58; move.date_planned,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'move_dest_id'&#58; 
move.move_dest_id.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'location_id'&#58; move.location_id.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'location_dest_id'&#58; 
move.location_dest_id.id,
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'state'&#58; move.state
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#125;
+&nbsp; &nbsp;
+&nbsp; &nbsp;# change the moves in the list so that they are part of the group 
headed by id 'id'
+&nbsp; &nbsp;def merge_moves &#40;list, group_id&#41;&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;stockmove_obj.write&#40;cr, uid, &#91;v.id for v in 
list&#93;, &#123;'move_group_id'&#58; merge_id,'state' &#58; 
'grouped'&#125;&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;stockmove_obj.write&#40;cr, uid, &#91;group_id&#93;, 
&#123;'group'&#58; True&#125;&#41;
+
&nbsp;&nbsp; &nbsp;# compute what the new orders should contain
&nbsp;&nbsp; &nbsp;new_orders = &#123;&#125;
&nbsp;&nbsp; &nbsp;for porder in &#91;order for order in 
order_obj.browse&#40;cr, uid, data&#91;'ids'&#93;&#41; if order.state == 
'draft'&#93;&#58;
@@ -77,6 +140,8 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;new_order = 
new_orders.setdefault&#40;order_key, &#40;&#123;&#125;, &#91;&#93;&#41;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;new_order&#91;1&#93;.append&#40;porder.id&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;order_infos = new_order&#91;0&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;# if no order details yet &#40;this is the first 
order for this partner/location&#41;, fill them in
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if not order_infos&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;order_infos.update&#40;&#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'origin'&#58; 
porder.origin,
@@ -93,46 +158,114 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#125;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;else&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;#order_infos&#91;'name'&#93; += ', 
%s' % porder.name
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# we already have the order details, so 
just append the notes from this order
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if porder.notes&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;order_infos&#91;'notes'&#93; += &#40;'\n%s' % &#40;porder.notes,&#41;&#41;
&nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;# work through the order lines
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;for order_line in porder.order_line&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# get a key based on the fields which 
must be unique
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;line_key = 
make_key&#40;order_line, &#40;'name', 'date_planned', 'taxes_id', 'price_unit', 
'notes', 'product_id', 'move_dest_id', 'account_analytic_id'&#41;&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # get a pointer to a line with the 
same key values
+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # if no match, then it will be 
empty, and we will fill it
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;o_line = 
order_infos&#91;'order_line'&#93;.setdefault&#40;line_key, &#123;&#125;&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# get the move_dest_id field
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;dest_val = getattr&#40;order_line, 
'move_dest_id'&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if not dest_val&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;dest_val = False
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;else&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;dest_val = dest_val.id
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if o_line&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# merge the line with 
an existing line
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;'product_qty'&#93; += order_line.product_qty * 
order_line.product_uom.factor / o_line&#91;'uom_factor'&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if full_merge&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;'move_dest_id_loc'&#93;.append 
&#40;order_line.move_dest_id&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;else&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# append a new 
"standalone" line
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;for field in 
&#40;'product_qty', 'product_uom'&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;field_val = getattr&#40;order_line, field&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
isinstance&#40;field_val, browse_record&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;field_val = field_val.id
-&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;field&#93; = field_val 
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;field&#93; = field_val
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;'uom_factor'&#93; = order_line.product_uom and 
order_line.product_uom.factor or 1.0
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if full_merge&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;o_line&#91;'move_dest_id_loc'&#93; = &#91;order_line.move_dest_id,&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# put in the move_dest_id value
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;o_line &#91;'move_dest_id'&#93; = 
dest_val
&nbsp;
&nbsp;&nbsp; &nbsp;wf_service = netsvc.LocalService&#40;"workflow"&#41;
&nbsp;
&nbsp;&nbsp; &nbsp;allorders = &#91;&#93;
&nbsp;&nbsp; &nbsp;for order_key, &#40;order_data, old_ids&#41; in 
new_orders.iteritems&#40;&#41;&#58;
-&nbsp; &nbsp;&nbsp; &nbsp;# skip merges with only one order
-&nbsp; &nbsp;&nbsp; &nbsp;if len&#40;old_ids&#41; < 2&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;# skip merges with only one order, unless we are 
merging items
+&nbsp; &nbsp;&nbsp; &nbsp;if len&#40;old_ids&#41; <2> 1&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# look for associated 
stock moves &#40;pointed to by move_dest_id&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_list = 
&#91;&#93;&nbsp; &nbsp;&nbsp; &nbsp;# list of move lines to group
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_id = -1&nbsp; 
&nbsp;&nbsp; &nbsp;# id of the group move created
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;for move in move_list&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# if this 
move has an associated move which is for the same product, add it to the list
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;rel_move = 
stockmove_obj.browse &#40;cr, uid, &#91;move.move_dest_id.id&#93;, 
&#123;&#125;&#41; &#91;0&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
rel_move.product_id.id == move.product_id.id&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;merge_list.append &#40;rel_move&#41;
+
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# if we got any, group them
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if len 
&#40;merge_list&#41; > 0&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move = 
get_stock_move &#40;merge_list &#91;0&#93;.id&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;del move 
&#91;'picking_id'&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move 
&#91;'product_qty'&#93; = value &#91;'product_qty'&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_id = 
stockmove_obj.create&#40;cr, uid, move&#41;;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# indicate 
that these items are now grouped
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_moves 
&#40;merge_list, merge_id&#41;
+
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# and now merge our 
original list, setting the quantity and move_dest_id correctly
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# we remove the 
picking_id, since we don't want the merged item to appear in the picking 
&#40;do we?&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move = get_stock_move 
&#40;move_list &#91;0&#93;.id&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;del move 
&#91;'picking_id'&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move 
&#91;'product_qty'&#93; = value &#91;'product_qty'&#93;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if merge_id != -1&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;move 
&#91;'move_dest_id'&#93; = merge_id
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_id = 
stockmove_obj.create&#40;cr, uid, move&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# indicate that these 
items are now grouped
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;merge_moves 
&#40;move_list, merge_id&#41;
+
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# update the order line to 
point to the new move
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;value 
&#91;'move_dest_id'&#93; = merge_id
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;value &#91;'group'&#93; = 
True
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;order_data&#91;'order_line'&#93; = &#91;&#40;0, 
0, value&#41; for value in 
order_data&#91;'order_line'&#93;.itervalues&#40;&#41;&#93;
-&nbsp; &nbsp;&nbsp; &nbsp;
+
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# create the new order
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;neworder_id = order_obj.create&#40;cr, uid, 
order_data&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;allorders.append&#40;neworder_id&#41;
&nbsp;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# make triggers pointing to the old orders 
point to the new order
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;for old_id in old_ids&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;proc_ids = proc_obj.search&#40;cr, uid, 
&#91;&#40;'purchase_id', '=', old_id&#41;&#93;&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;proc_obj.write&#40;cr, uid, proc_ids, 
&#123;'purchase_id'&#58; neworder_id,&#125;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;wf_service.trg_redirect&#40;uid, 
'purchase.order', old_id, neworder_id, cr&#41;
+
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# cancel the old order
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;wf_service.trg_validate&#40;uid, 
'purchase.order', old_id, 'purchase_cancel', cr&#41;
&nbsp;
&nbsp;&nbsp; &nbsp;return &#123;
Index&#58; bin/addons/purchase/purchase.py
===================================================================
--- bin/addons/purchase/purchase.py&nbsp; &nbsp;&#40;revision 666&#41;
+++ bin/addons/purchase/purchase.py&nbsp; &nbsp;&#40;working copy&#41;
@@ -252,7 +252,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;continue
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
order_line.product_id.product_tmpl_id.type in &#40;'product', 'consu'&#41;&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;dest = 
order.location_id.id
-&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;self.pool.get&#40;'stock.move'&#41;.create&#40;cr, uid, &#123;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;fields = 
&#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'name'&#58; 'PO&#58;'+order_line.name,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'product_id'&#58; order_line.product_id.id,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'product_qty'&#58; order_line.product_qty,
@@ -266,7 +266,12 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'move_dest_id'&#58; order_line.move_dest_id.id,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'state'&#58; 'assigned',
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'purchase_line_id'&#58; order_line.id,
-&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#125;&#41;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&#125;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;# for a 
group, add the group info also
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
order_line.group&#58;
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;fields &#91;'group'&#93; = True
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;fields &#91;'move_group_id'&#93; = 
order_line.move_dest_id.move_group_id.id
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;self.pool.get&#40;'stock.move'&#41;.create&#40;cr, uid, fields&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if 
order_line.move_dest_id&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;self.pool.get&#40;'stock.move'&#41;.write&#40;cr, uid, 
&#91;order_line.move_dest_id.id&#93;, 
&#123;'location_id'&#58;order.location_id.id&#125;&#41;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;wf_service = 
netsvc.LocalService&#40;"workflow"&#41;
@@ -310,6 +315,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'notes'&#58; fields.text&#40;'Notes'&#41;,
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'order_id'&#58; 
fields.many2one&#40;'purchase.order', 'Order Ref', select=True, required=True, 
ondelete='cascade'&#41;,
&nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;'account_analytic_id'&#58;fields.many2one&#40;'account.analytic.account', 
'Analytic Account',&#41;,
+&nbsp; &nbsp;&nbsp; &nbsp;'group'&#58;fields.boolean&#40;'Group', 
readonly=True, select=True, help = "true if order line was created from a group 
of others"&#41;,
&nbsp;&nbsp; &nbsp;&#125;
&nbsp;&nbsp; &nbsp;_defaults = &#123;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;'product_qty'&#58; lambda *a&#58; 1.0
Index&#58; bin/addons/purchase/purchase_view.xml
===================================================================
--- bin/addons/purchase/purchase_view.xml&nbsp; &nbsp;&#40;revision 666&#41;
+++ bin/addons/purchase/purchase_view.xml&nbsp; &nbsp;&#40;working copy&#41;
@@ -138,6 +138,7 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
+&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;</page><page>
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 
&nbsp;<field>
Index&#58; bin/workflow/workitem.py
===================================================================
--- bin/workflow/workitem.py&nbsp; &nbsp;&#40;revision 666&#41;
+++ bin/workflow/workitem.py&nbsp; &nbsp;&#40;working copy&#41;
@@ -95,7 +95,6 @@
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;instance.validate&#40;cr, 
i&#91;0&#93;, &#40;ident&#91;0&#93;,i&#91;1&#93;,i&#91;2&#93;&#41;, 
activity&#91;'signal_send'&#93;, force_running=True&#41;
&nbsp;
&nbsp;
-
&nbsp;&nbsp; &nbsp;if activity&#91;'kind'&#93;=='dummy'&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if workitem&#91;'state'&#93;=='active'&#58;
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_state_set&#40;cr, workitem, 
activity, 'complete', ident&#41;




------------------------
--
Simon Glass
Christchurch
New Zealand




_______________________________________________
Tinyerp-users mailing list
http://tiny.be/mailman/listinfo/tinyerp-users

Reply via email to