From c7326c55fbb2d87a70790bbd055e9996cac1f00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 23 Mar 2013 15:42:36 +0100 Subject: [PATCH] Use reference fields Merge all shipment Many2One into shipment Reference Add origin Reference on Stock Move issue2642 review717002 --- CHANGELOG | 2 ++ __init__.py | 2 +- move.py | 93 +++++++++++++++++++++++++++++++++-------------------- move.xml | 2 +- shipment.py | 55 ++++++++++++++++++------------- 5 files changed, 96 insertions(+), 58 deletions(-) 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