diff --git a/CHANGELOG b/CHANGELOG
index 6cdd2bbc8d..2da2ba28eb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+* Merge all shipment Many2One into shipment Reference
+* Add origin Reference on Stock Move
* Add workflow to stock move
Version 2.6.0 - 2012-10-22
diff --git a/__init__.py b/__init__.py
index 4a3470707a..538a76a156 100644
--- a/__init__.py
+++ b/__init__.py
@@ -16,6 +16,7 @@ def register():
Location,
Party,
ProductsByLocationsStart,
+ Move,
ShipmentIn,
ShipmentInReturn,
ShipmentOut,
@@ -27,7 +28,6 @@ def register():
AssignShipmentInReturnAssignFailed,
Period,
Cache,
- Move,
Template,
Product,
ProductByLocationStart,
diff --git a/move.py b/move.py
index 4af38b30f3..8a5383def8 100644
--- a/move.py
+++ b/move.py
@@ -50,30 +50,17 @@ class Move(Workflow, ModelSQL, ModelView):
to_location = fields.Many2One("stock.location", "To Location", select=True,
required=True, states=STATES, depends=DEPENDS,
domain=[('type', 'not in', ('warehouse', 'view'))])
- shipment_in = fields.Many2One('stock.shipment.in', 'Supplier Shipment',
- domain=[('company', '=', Eval('company'))], depends=['company'],
- readonly=True, select=True, ondelete='CASCADE')
- shipment_out = fields.Many2One('stock.shipment.out', 'Customer Shipment',
- domain=[('company', '=', Eval('company'))], depends=['company'],
- readonly=True, select=True, ondelete='CASCADE')
- shipment_out_return = fields.Many2One('stock.shipment.out.return',
- 'Customer Return Shipment', readonly=True, select=True,
- domain=[('company', '=', Eval('company'))], depends=['company'],
- ondelete='CASCADE')
- shipment_in_return = fields.Many2One('stock.shipment.in.return',
- 'Supplier Return Shipment', readonly=True, select=True,
- domain=[('company', '=', Eval('company'))], depends=['company'],
- ondelete='CASCADE')
- shipment_internal = fields.Many2One('stock.shipment.internal',
- 'Internal Shipment', readonly=True, select=True, ondelete='CASCADE',
- domain=[('company', '=', Eval('company'))], depends=['company'])
+ shipment = fields.Reference('Shipment', selection='get_shipment',
+ readonly=True, select=True)
+ origin = fields.Reference('Origin', selection='get_origin', select=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
planned_date = fields.Date("Planned Date", states={
'readonly': (In(Eval('state'), ['cancel', 'assigned', 'done'])
- | Eval('shipment_in') | Eval('shipment_out')
- | Eval('shipment_in_return') | Eval('shipment_out_return')
- | Eval('shipment_internal'))
- }, depends=['state', 'shipment_in', 'shipment_out',
- 'shipment_in_return', 'shipment_out_return', 'shipment_internal'],
+ | Eval('shipment'))
+ }, depends=['state', 'shipment'],
select=True)
effective_date = fields.Date("Effective Date", readonly=True, select=True)
state = fields.Selection([
@@ -122,18 +109,6 @@ class Move(Workflow, ModelSQL, ModelView):
('check_from_to_locations',
'CHECK(from_location != to_location)',
'Source and destination location must be different'),
- ('check_shipment',
- ('CHECK((COALESCE(shipment_in, 0) / COALESCE(shipment_in, 1) '
- '+ COALESCE(shipment_out, 0) / '
- 'COALESCE(shipment_out, 1) '
- '+ COALESCE(shipment_internal, 0) / '
- 'COALESCE(shipment_internal, 1) '
- '+ COALESCE(shipment_in_return, 0) / '
- 'COALESCE(shipment_in_return, 1) '
- '+ COALESCE(shipment_out_return, 0) / '
- 'COALESCE(shipment_out_return, 1)) '
- '<= 1)'),
- 'Move can be on only one Shipment'),
]
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
@@ -213,6 +188,22 @@ class Move(Workflow, ModelSQL, ModelView):
table = TableHandler(cursor, cls, module_name)
table.drop_constraint('check_packing_in_out')
+ # Migration from 2.6: merge all shipments
+ table.drop_constraint('check_shipment')
+ shipments = {
+ 'shipment_in': 'stock.shipment.in',
+ 'shipment_out': 'stock.shipment.out',
+ 'shipment_out_return': 'stock.shipment.out.return',
+ 'shipment_in_return': 'stock.shipment.in.return',
+ 'shipment_internal': 'stock.shipment.internal',
+ }
+ for column, model in shipments.iteritems():
+ if table.column_exist(column):
+ cursor.execute('UPDATE "' + cls._table + '" '
+ 'SET shipment = \'' + model + ',\' || "' + column + '" '
+ 'WHERE "' + column + '" IS NOT NULL')
+ table.drop_column(column)
+
# Add index on create_date
table.index_action('create_date', action='add')
@@ -306,6 +297,40 @@ class Move(Workflow, ModelSQL, ModelView):
return True
return False
+ @staticmethod
+ def _get_shipment():
+ 'Return list of Model names for shipment Reference'
+ return [
+ 'stock.shipment.in',
+ 'stock.shipment.out',
+ 'stock.shipment.out.return',
+ 'stock.shipment.in.return',
+ 'stock.shipment.internal',
+ ]
+
+ @classmethod
+ def get_shipment(cls):
+ Model = Pool().get('ir.model')
+ models = cls._get_shipment()
+ models = Model.search([
+ ('model', 'in', models),
+ ])
+ return [(None, '')] + [(m.model, m.name) for m in models]
+
+ @staticmethod
+ def _get_origin():
+ 'Return list of Model names for origin Reference'
+ return []
+
+ @classmethod
+ def get_origin(cls):
+ Model = Pool().get('ir.model')
+ models = cls._get_origin()
+ models = Model.search([
+ ('model', 'in', models),
+ ])
+ return [(None, '')] + [(m.model, m.name) for m in models]
+
@classmethod
def validate(cls, moves):
super(Move, cls).validate(moves)
diff --git a/move.xml b/move.xml
index 5c2c2fbcae..11d7ecdc16 100644
--- a/move.xml
+++ b/move.xml
@@ -52,7 +52,7 @@ this repository contains the full copyright notices and license terms. -->
From Suppliers Waiting
- [('from_location.type', '=', 'supplier'), ('state', '=', 'draft'), ('shipment_in', '=', None)]
+ [('from_location.type', '=', 'supplier'), ('state', '=', 'draft'), ('shipment', '=', None)]
diff --git a/shipment.py b/shipment.py
index 52da7cac34..c2b136147f 100644
--- a/shipment.py
+++ b/shipment.py
@@ -80,7 +80,7 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
incoming_moves = fields.Function(fields.One2Many('stock.move', None,
'Incoming Moves',
add_remove=[
- ('shipment_in', '=', None),
+ ('shipment', '=', None),
('from_location', '=', Eval('supplier_location')),
('state', '=', 'draft'),
('to_location', '=', Eval('warehouse_input')),
@@ -111,7 +111,7 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
depends=['state', 'warehouse', 'warehouse_input',
'warehouse_storage', 'company']),
'get_inventory_moves', setter='set_inventory_moves')
- moves = fields.One2Many('stock.move', 'shipment_in', 'Moves',
+ moves = fields.One2Many('stock.move', 'shipment', 'Moves',
domain=[('company', '=', Eval('company'))], readonly=True,
depends=['company'])
code = fields.Char("Code", size=None, select=True, readonly=True)
@@ -196,10 +196,11 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
and TableHandler.table_exist(cursor, Move._table)):
cursor.execute('SELECT shipment.id, MAX(move.company) '
'FROM "%s" AS shipment '
- 'INNER JOIN "%s" AS move ON shipment.id = move.shipment_in '
+ 'INNER JOIN "%s" AS move '
+ 'ON \'%s,\' || shipment.id = move.shipment '
'GROUP BY shipment.id '
'ORDER BY MAX(move.company)'
- % (cls._table, Move._table))
+ % (cls._table, Move._table, cls.__name__))
for company_id, values in itertools.groupby(cursor.fetchall(),
operator.itemgetter(1)):
shipment_ids = [x[0] for x in values]
@@ -357,7 +358,7 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
move.uom = incoming_move.uom
move.quantity = incoming_move.quantity
move.from_location = incoming_move.to_location
- move.to_location = incoming_move.shipment_in.warehouse.storage_location
+ move.to_location = incoming_move.shipment.warehouse.storage_location
move.state = Move.default_state()
# Product will be considered in stock only when the inventory
# move will be made:
@@ -381,11 +382,13 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
@classmethod
def delete(cls, shipments):
+ Move = Pool().get('stock.move')
# Cancel before delete
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
+ Move.delete([m for s in shipments for m in s.moves])
super(ShipmentIn, cls).delete(shipments)
@classmethod
@@ -461,7 +464,7 @@ class ShipmentInReturn(Workflow, ModelSQL, ModelView):
Bool(Eval('moves'))),
}, domain=[('type', '=', 'supplier')],
depends=['state', 'moves'])
- moves = fields.One2Many('stock.move', 'shipment_in_return', 'Moves',
+ moves = fields.One2Many('stock.move', 'shipment', 'Moves',
states={
'readonly': And(Or(Not(Equal(Eval('state'), 'draft')),
Not(Bool(Eval('from_location')))),
@@ -552,10 +555,10 @@ class ShipmentInReturn(Workflow, ModelSQL, ModelView):
cursor.execute('SELECT shipment.id, MAX(move.company) '
'FROM "%s" AS shipment '
'INNER JOIN "%s" AS move '
- 'ON shipment.id = move.shipment_in_return '
+ 'ON \'%s,\' || shipment.id = move.shipment '
'GROUP BY shipment.id '
'ORDER BY MAX(move.company)'
- % (cls._table, Move._table))
+ % (cls._table, Move._table, cls.__name__))
for company_id, values in itertools.groupby(cursor.fetchall(),
operator.itemgetter(1)):
shipment_ids = [x[0] for x in values]
@@ -621,11 +624,13 @@ class ShipmentInReturn(Workflow, ModelSQL, ModelView):
@classmethod
def delete(cls, shipments):
+ Move = Pool().get('stock.move')
# Cancel before delete
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
+ Move.delete([m for s in shipments for m in s.moves])
super(ShipmentInReturn, cls).delete(shipments)
@classmethod
@@ -795,7 +800,7 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
depends=['state', 'warehouse', 'warehouse_storage',
'warehouse_output', 'company']),
'get_inventory_moves', setter='set_inventory_moves')
- moves = fields.One2Many('stock.move', 'shipment_out', 'Moves',
+ moves = fields.One2Many('stock.move', 'shipment', 'Moves',
domain=[('company', '=', Eval('company'))], depends=['company'],
readonly=True)
code = fields.Char("Code", size=None, select=True, readonly=True)
@@ -889,10 +894,11 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
and TableHandler.table_exist(cursor, Move._table)):
cursor.execute('SELECT shipment.id, MAX(move.company) '
'FROM "%s" AS shipment '
- 'INNER JOIN "%s" AS move ON shipment.id = move.shipment_out '
+ 'INNER JOIN "%s" AS move '
+ 'ON \'%s,\' || shipment.id = move.shipment '
'GROUP BY shipment.id '
'ORDER BY MAX(move.company)'
- % (cls._table, Move._table))
+ % (cls._table, Move._table, cls.__name__))
for company_id, values in itertools.groupby(cursor.fetchall(),
operator.itemgetter(1)):
shipment_ids = [x[0] for x in values]
@@ -1015,12 +1021,12 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
continue
to_create.append({
'from_location': (
- move.shipment_out.warehouse.storage_location.id),
+ move.shipment.warehouse.storage_location.id),
'to_location': move.from_location.id,
'product': move.product.id,
'uom': move.uom.id,
'quantity': move.quantity,
- 'shipment_out': shipment.id,
+ 'shipment': str(shipment),
'planned_date': move.planned_date,
'state': 'draft',
'company': move.company.id,
@@ -1085,7 +1091,7 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
'product': move.product.id,
'uom': move.uom.id,
'quantity': out_quantity,
- 'shipment_out': shipment.id,
+ 'shipment': str(shipment),
'state': 'draft',
'planned_date': shipment.planned_date,
'company': move.company.id,
@@ -1189,11 +1195,13 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
@classmethod
def delete(cls, shipments):
+ Move = Pool().get('stock.move')
# Cancel before delete
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
+ Move.delete([m for s in shipments for m in s.moves])
super(ShipmentOut, cls).delete(shipments)
@staticmethod
@@ -1310,7 +1318,7 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
depends=['state', 'warehouse', 'warehouse_input',
'warehouse_storage', 'company']),
'get_inventory_moves', setter='set_inventory_moves')
- moves = fields.One2Many('stock.move', 'shipment_out_return', 'Moves',
+ moves = fields.One2Many('stock.move', 'shipment', 'Moves',
domain=[('company', '=', Eval('company'))], depends=['company'],
readonly=True)
code = fields.Char("Code", size=None, select=True, readonly=True)
@@ -1379,10 +1387,10 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
cursor.execute('SELECT shipment.id, MAX(move.company) '
'FROM "%s" AS shipment '
'INNER JOIN "%s" AS move '
- 'ON shipment.id = move.shipment_out_return '
+ 'ON \'%s,\' || shipment.id = move.shipment '
'GROUP BY shipment.id '
'ORDER BY MAX(move.company)'
- % (cls._table, Move._table))
+ % (cls._table, Move._table, cls.__name__))
for company_id, values in itertools.groupby(cursor.fetchall(),
operator.itemgetter(1)):
shipment_ids = [x[0] for x in values]
@@ -1532,11 +1540,13 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
@classmethod
def delete(cls, shipments):
+ Move = Pool().get('stock.move')
# Cance before delete
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
+ Move.delete([m for s in shipments for m in s.moves])
super(ShipmentOutReturn, cls).delete(shipments)
@classmethod
@@ -1587,8 +1597,7 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
move.uom = incoming_move.uom
move.quantity = incoming_move.quantity
move.from_location = incoming_move.to_location
- move.to_location = incoming_move.shipment_out_return.warehouse.\
- storage_location
+ move.to_location = incoming_move.shipment.warehouse.storage_location
move.state = Move.default_state()
# Product will be considered in stock only when the inventory
# move will be made:
@@ -1699,7 +1708,7 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
('type', 'not in',
['supplier', 'customer', 'warehouse', 'view']),
], depends=['state', 'moves'])
- moves = fields.One2Many('stock.move', 'shipment_internal', 'Moves',
+ moves = fields.One2Many('stock.move', 'shipment', 'Moves',
states={
'readonly': ((Eval('state') != 'draft')
| ~Eval('from_location') | ~Eval('to_location')),
@@ -1796,10 +1805,10 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
cursor.execute('SELECT shipment.id, MAX(move.company) '
'FROM "%s" AS shipment '
'INNER JOIN "%s" AS move '
- 'ON shipment.id = move.shipment_internal '
+ 'ON \'%s,\' || shipment.id = move.shipment '
'GROUP BY shipment.id '
'ORDER BY MAX(move.company)'
- % (cls._table, Move._table))
+ % (cls._table, Move._table, cls.__name__))
for company_id, values in itertools.groupby(cursor.fetchall(),
operator.itemgetter(1)):
shipment_ids = [x[0] for x in values]
@@ -1838,11 +1847,13 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
@classmethod
def delete(cls, shipments):
+ Move = Pool().get('stock.move')
# Cancel before delete
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
+ Move.delete([m for s in shipments for m in s.moves])
super(ShipmentInternal, cls).delete(shipments)
@classmethod