diff --git a/move.py b/move.py
index c714ac9ec8..21b39a4ca4 100644
--- a/move.py
+++ b/move.py
@@ -26,16 +26,10 @@ class Move(OSV):
to_location = fields.Many2One(
"stock.location", "To Location", select=1, required=True,
states=STATES, domain="[('type', '!=', 'warehouse')]",)
- incoming_packing_in = fields.Many2One(
- "stock.packing.in", "Supplier Packing", states=STATES, select=1)
- inventory_packing_in = fields.Many2One(
- "stock.packing.in", "Inventory Supplier Packing", states=STATES,
- select=1)
- outgoing_packing_out = fields.Many2One(
- "stock.packing.out", "Customer Packing", states=STATES, select=1)
- inventory_packing_out = fields.Many2One(
- "stock.packing.out", "Inventory Customer Packing", states=STATES,
- select=1)
+ packing_in = fields.Many2One('stock.packing.in', 'Supplier Packing',
+ readonly=True, select=1)
+ packing_out = fields.Many2One('stock.packing.out', 'Customer Packing',
+ readonly=True, select=1)
planned_date = fields.Date("Planned Date", states=STATES,)
effective_date = fields.Date("Effective Date", readonly=True)
state = fields.Selection([
@@ -57,47 +51,16 @@ class Move(OSV):
self._sql_constraints += [
('check_move_qty_pos',
'CHECK(quantity >= 0.0)', 'Move quantity must be positive'),
- ]
- self._constraints += [
- ('check_locations',
- 'Invalid locations', []),
+ ('check_from_to_locations',
+ 'CHECK(from_location != to_location)',
+ 'Source and destination location must be different'),
+ ('check_packing_in_out',
+ 'CHECK(NOT(packing_in IS NOT NULL ' \
+ 'AND packing_out IS NOT NULL))',
+ 'Move can not be in both Supplier and Customer Packing'),
]
self._order[0] = ('id', 'DESC')
- def check_locations(self, cursor, user, ids, context=None):
- for move in self.browse(cursor, user, ids, context=context):
- if move.from_location.id == move.to_location.id:
- return False
- if move.incoming_packing_in:
- if move.incoming_packing_in.warehouse.input_location.id \
- != move.to_location.id:
- return False
- if move.from_location.type and move.from_location.type \
- not in ('supplier', 'customer'):
- return False
- for packing_move in move.incoming_packing_in.incoming_moves:
- if packing_move.from_location.id != move.from_location.id:
- return False
- if move.inventory_packing_in and \
- move.inventory_packing_in.warehouse.input_location.id \
- != move.from_location.id:
- return False
- if move.inventory_packing_out and \
- move.inventory_packing_out.warehouse.output_location.id \
- != move.to_location.id:
- return False
- if move.outgoing_packing_out:
- if move.outgoing_packing_out.warehouse.output_location.id \
- != move.from_location.id:
- return False
- if move.to_location.type and \
- move.to_location.type not in ('supplier', 'customer'):
- return False
- for packing_move in move.outgoing_packing_out.outgoing_moves:
- if packing_move.to_location.id != move.to_location.id:
- return False
- return True
-
def default_to_location(self, cursor, user, context=None):
if context and context.get('warehouse') and context.get('type'):
wh_location = self.pool.get('stock.location').browse(
@@ -191,12 +154,6 @@ class Move(OSV):
Move()
-class CreatePackingWarn(WizardOSV):
- _name = 'stock.move.create_packing.warn'
-
-CreatePackingWarn()
-
-
class CreatePacking(Wizard):
'Create Packing'
_name = 'stock.move.create_packing'
@@ -221,7 +178,7 @@ class CreatePacking(Wizard):
# Collect moves by incoming location
moves_by_location = {}
for move in moves:
- if move.incoming_packing_in or move.inventory_packing_in:
+ if move.packing_in:
raise ExceptWizard(
'UserError', 'Moves cannot be already in a packing.')
if move.state != 'waiting':
@@ -235,15 +192,14 @@ class CreatePacking(Wizard):
moves_by_location[location].append(move.id)
# Fetch warehouse for these locations
- wh_location_ids = location_obj.search(
- cursor, user,
- [('input_location', 'in',
- [l for l in moves_by_location]),
- ('type', '=', 'warehouse')], context=context)
+ wh_location_ids = location_obj.search(cursor, user, [
+ ('input_location', 'in', moves_by_location.keys()),
+ ('type', '=', 'warehouse'),
+ ], context=context)
wh_locations = location_obj.browse(
cursor, user, wh_location_ids, context=context)
loc2wh = dict(
- [( whl.input_location.id, whl.id) for whl in wh_locations])
+ [(whl.input_location.id, whl.id) for whl in wh_locations])
packing_ids = []
for location, move_ids in moves_by_location.iteritems():
@@ -253,10 +209,10 @@ class CreatePacking(Wizard):
'UserError',
'Moves must have a final destination '\
'who is an input location of a wharehouse.')
- pid = packing_obj.create(
- cursor, user,
- {'incoming_moves': [('set',move_ids)], 'warehouse': whl},
- context=context)
+ pid = packing_obj.create(cursor, user, {
+ 'incoming_moves': [('set', move_ids)],
+ 'warehouse': whl,
+ }, context=context)
packing_ids.append(pid)
@@ -269,10 +225,8 @@ class CreatePacking(Wizard):
model_data = model_data_obj.browse(cursor, user, model_data_ids[0],
context=context)
res = act_window_obj.read(cursor, user, model_data.db_id,
- context=context)
- res["domain"]= str([('id', 'in', packing_ids)])
-
+ context=context)
+ res["domain"] = str([('id', 'in', packing_ids)])
return res
CreatePacking()
-
diff --git a/move.xml b/move.xml
index 0d26aa2133..6102a42d5d 100644
--- a/move.xml
+++ b/move.xml
@@ -110,9 +110,7 @@
Moves from suppliers to proceed
stock.move
form
- [('from_location.type', '=', 'supplier'),
- ('state','in',['draft','waiting']),('incoming_packing_in','=',False),
- ('inventory_packing_in','=',False)]
+ [('from_location.type', '=', 'supplier'), ('state','in',['draft','waiting']), ('_packing_in','=',False)]
@@ -177,22 +175,6 @@
action="act_move_form_cust_proceed"
id="menu_move_form_cust_proceed"/>
-
-
-
- stock.move.create_packing.warn
- form
-
-
-
-
-
- ]]>
-
-
-
Create Packing
stock.move.create_packing
@@ -204,6 +186,5 @@
-
diff --git a/packing.py b/packing.py
index 9e7540929a..dffcacc5de 100644
--- a/packing.py
+++ b/packing.py
@@ -16,27 +16,32 @@ class PackingIn(OSV):
effective_date =fields.DateTime('Effective Date', readonly=True)
planned_date = fields.DateTime('Planned Date', readonly=True)
- warehouse = fields.Many2One(
- 'stock.location', "Warehouse", required=True, states=STATES,
- domain="[('type', '=', 'warehouse')]",)
- incoming_moves = fields.One2Many(
- 'stock.move', 'incoming_packing_in', 'Incoming Moves',
- states={'readonly': "state in ('received', 'done')",},
- context="{'warehouse': warehouse, "\
- "'packing_state': state, 'type':'incoming'}")
- inventory_moves = fields.One2Many(
- 'stock.move', 'inventory_packing_in', 'Inventory Moves',
- states={'readonly': "state in ('draft', 'waiting')",},
- context="{'warehouse': warehouse, "\
- "'packing_state': state, 'type':'inventory_in'}")
+ warehouse = fields.Many2One('stock.location', "Warehouse",
+ required=True, states=STATES, domain="[('type', '=', 'warehouse')]")
+ incoming_moves = fields.Function('get_incoming_moves', type='one2many',
+ relation='stock.move', string='Incoming Moves',
+ fnct_inv='set_incoming_moves',
+ states={
+ 'readonly': "state in ('received', 'done')",
+ }, context="{'warehouse': warehouse, "\
+ "'packing_state': state, 'type':'incoming'}")
+ inventory_moves = fields.Function('get_inventory_moves', type='one2many',
+ relation='stock.move', string='Inventory Moves',
+ fnct_inv='set_inventory_moves',
+ states={
+ 'readonly': "state in ('draft', 'waiting')",
+ }, context="{'warehouse': warehouse, "\
+ "'packing_state': state, 'type':'inventory_in'}")
+ moves = fields.One2Many('stock.move', 'packing_in', 'Moves',
+ readonly=True)
code = fields.Char("Code", size=None, select=1, readonly=True,)
- state = fields.Selection(
- [('draft', 'Draft'),
- ('done', 'Done'),
- ('cancel', 'Cancel'),
- ('waiting', 'Waiting'),
- ('received', 'Received')],
- 'State', readonly=True)
+ state = fields.Selection([
+ ('draft', 'Draft'),
+ ('done', 'Done'),
+ ('cancel', 'Cancel'),
+ ('waiting', 'Waiting'),
+ ('received', 'Received'),
+ ], 'State', readonly=True)
def __init__(self):
super(PackingIn, self).__init__()
@@ -46,13 +51,98 @@ class PackingIn(OSV):
'set_state_draft',
'set_state_cancel',
'set_state_received',
- 'create_inventory_moves',
]
self._order[0] = ('id', 'DESC')
def default_state(self, cursor, user, context=None):
return 'draft'
+ def get_incoming_moves(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for packing in self.browse(cursor, user, ids, context=context):
+ res[packing.id] = []
+ for move in packing.moves:
+ if move.to_location.id == packing.warehouse.input_location.id:
+ res[packing.id].append(move.id)
+ return res
+
+ def set_incoming_moves(self, cursor, user, packing_id, name, value, arg,
+ context=None):
+ move_obj = self.pool.get('stock.move')
+ packing = self.browse(cursor, user, packing_id, context=context)
+ for act in value:
+ if act[0] == 'create':
+ if 'to_location' in act[1]:
+ if act[1]['to_location'] != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Incoming Moves must ' \
+ 'have input location as destination location!')
+ elif act[0] == 'write':
+ if 'to_location' in act[2]:
+ if act[2]['to_location'] != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Incoming Moves must ' \
+ 'have input location as destination location!')
+ elif act[0] == 'add':
+ move = move_obj.browse(cursor, user, act[1], context=context)
+ if move.to_location.id != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Incoming Moves must ' \
+ 'have input location as destination location!')
+ elif act[0] == 'set':
+ moves = move_obj.browse(cursor, user, act[1], context=context)
+ for move in moves:
+ if move.to_location.id != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Incoming Moves must ' \
+ 'have input location as destination location!')
+ self.write(cursor, user, packing_id, {
+ 'moves': value,
+ }, context=context)
+
+ def get_inventory_moves(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for packing in self.browse(cursor, user, ids, context=context):
+ res[packing.id] = []
+ for move in packing.moves:
+ if move.from_location.id == packing.warehouse.input_location.id:
+ res[packing.id].append(move.id)
+ return res
+
+ def set_inventory_moves(self, cursor, user, packing_id, name, value, arg,
+ context=None):
+ move_obj = self.pool.get('stock.move')
+ packing = self.browse(cursor, user, packing_id, context=context)
+ for act in value:
+ if act[0] == 'create':
+ if 'from_location' in act[1]:
+ if act[1]['from_location'] != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have input location as source location!')
+ elif act[0] == 'write':
+ if 'from_location' in act[2]:
+ if act[2]['from_location'] != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have input location as source location!')
+ elif act[0] == 'add':
+ move = move_obj.browse(cursor, user, act[1], context=context)
+ if move.from_location.id != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have input location as source location!')
+ elif act[0] == 'set':
+ moves = move_obj.browse(cursor, user, act[1], context=context)
+ for move in moves:
+ if move.from_location.id != \
+ packing.warehouse.input_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have input location as source location!')
+ self.write(cursor, user, packing_id, {
+ 'moves': value,
+ }, context=context)
+
def set_state_done(self, cursor, user, packing_id, context=None):
move_obj = self.pool.get('stock.move')
packing = self.browse(cursor, user, packing_id, context=context)
@@ -88,8 +178,6 @@ class PackingIn(OSV):
cursor, user, [m.id for m in packing.incoming_moves], context)
self.write(
cursor, user, packing_id, {'state':'received'}, context=context)
- self.create_inventory_moves(
- cursor, user, [packing_id], context=context)
def set_state_draft(self, cursor, user, packing_id, context=None):
move_obj = self.pool.get('stock.move')
@@ -107,37 +195,28 @@ class PackingIn(OSV):
return super(PackingIn, self).create(
cursor, user, values, context=context)
- def _store_location(self, cursor, user, incoming_move, context=None):
- return incoming_move.incoming_packing_in.warehouse.storage_location.id
+ def _get_inventory_moves(self, cursor, user, incoming_move, context=None):
+ res = {}
+ if incoming_move.quantity <= 0.0:
+ return None
+ res['product'] = incoming_move.product.id
+ res['uom'] = incoming_move.uom.id
+ res['quantity'] = incoming_move.quantity
+ res['from_location'] = incoming_move.to_location.id
+ res['to_location'] = incoming_move.packing_in.warehouse.\
+ storage_location.id
+ res['state'] = 'waiting'
+ return res
- def create_inventory_moves(self, cursor, user, ids, context=None):
- move_obj = self.pool.get('stock.move')
- for packing in self.browse(cursor, user, ids, context=context):
- product_balance = {}
- for move in packing.inventory_moves:
- key = (move.product.id, move.uom.id, move.from_location.id)
- if key in product_balance:
- product_balance[key] += move.quantity
- else:
- product_balance[key] = move.quantity
-
- for move in packing.incoming_moves:
- key = (move.product.id, move.uom.id, move.to_location.id)
- if key in product_balance and \
- product_balance[key] >= move.quantity:
- product_balance[key] -= move.quantity
- else:
- values = {
- 'product': move.product.id,
- 'uom': move.uom.id,
- 'quantity': move.quantity,
- 'from_location': move.to_location.id,
- 'to_location': self._store_location(
- cursor, user, move, context=context),
- 'inventory_packing_in': packing.id,
- 'state': 'waiting',
- }
- move_obj.create(cursor, user, values, context=context)
+ def create_inventory_moves(self, cursor, user, packing_id, context=None):
+ packing = self.browse(cursor, user, packing_id, context=context)
+ for incoming_move in packing.incoming_moves:
+ vals = self._get_inventory_moves(cursor, user, incoming_move,
+ context=context)
+ if vals:
+ self.write(cursor, user, packing.id, {
+ 'inventory_moves': [('create', vals)]
+ }, context=context)
PackingIn()
@@ -150,33 +229,39 @@ class PackingOut(OSV):
effective_date =fields.DateTime('Effective Date', readonly=True)
planned_date = fields.DateTime('Planned Date', readonly=True)
- warehouse = fields.Many2One(
- 'stock.location', "Warehouse", required=True,
- states={'readonly': "state != 'draft'",},
- domain="[('type', '=', 'warehouse')]",)
- customer_location = fields.Many2One(
- 'stock.location', "Customer Location", required=True,
- states={'readonly': "state != 'draft'",},
- domain="[('type', '=', 'customer')]",)
- outgoing_moves = fields.One2Many(
- 'stock.move', 'outgoing_packing_out', 'Outgoing Moves',
- states={'readonly':"state != 'ready'",},
- context="{'warehouse': warehouse, "\
- "'packing_state': state, 'type':'outgoing',}")
- inventory_moves = fields.One2Many(
- 'stock.move', 'inventory_packing_out', 'Inventory Moves',
- states={'readonly':"state in ('ready', 'done')",},
- context="{'warehouse': warehouse, "\
- "'packing_state': state, 'type':'inventory_out',}")
- code = fields.Char("Code", size=None, select=1, readonly=True,)
- state = fields.Selection(
- [('draft', 'Draft'),
- ('done', 'Done'),
- ('cancel', 'Cancel'),
- ('assigned', 'Assigned'),
- ('ready', 'Ready'),
- ('waiting', 'Waiting')],
- 'State', readonly=True)
+ warehouse = fields.Many2One('stock.location', "Warehouse", required=True,
+ states={
+ 'readonly': "state != 'draft'",
+ }, domain="[('type', '=', 'warehouse')]")
+ customer_location = fields.Many2One('stock.location', "Customer Location",
+ required=True, states={
+ 'readonly': "state != 'draft'",
+ }, domain="[('type', '=', 'customer')]")
+ outgoing_moves = fields.Function('get_outgoing_moves', type='one2many',
+ relation='stock.move', string='Outgoing Moves',
+ fnct_inv='set_outgoing_moves',
+ states={
+ 'readonly':"state != 'ready'",
+ }, context="{'warehouse': warehouse, "\
+ "'packing_state': state, 'type':'outgoing',}")
+ inventory_moves = fields.Function('get_inventory_moves', type='one2many',
+ relation='stock.move', string='Inventory Moves',
+ fnct_inv='set_inventory_moves',
+ states={
+ 'readonly':"state in ('ready', 'done')",
+ }, context="{'warehouse': warehouse, "\
+ "'packing_state': state, 'type':'inventory_out',}")
+ moves = fields.One2Many('stock.move', 'packing_in', 'Moves',
+ readonly=True)
+ code = fields.Char("Code", size=None, select=1, readonly=True)
+ state = fields.Selection([
+ ('draft', 'Draft'),
+ ('done', 'Done'),
+ ('cancel', 'Cancel'),
+ ('assigned', 'Assigned'),
+ ('ready', 'Ready'),
+ ('waiting', 'Waiting'),
+ ], 'State', readonly=True)
def __init__(self):
super(PackingOut, self).__init__()
@@ -195,6 +280,94 @@ class PackingOut(OSV):
def default_state(self, cursor, user, context=None):
return 'draft'
+ def get_outgoing_moves(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for packing in self.browse(cursor, user, ids, context=context):
+ res[packing.id] = []
+ for move in packing.moves:
+ if move.from_location.id == \
+ packing.warehouse.output_location.id:
+ res[packing.id].append(move.id)
+ return res
+
+ def set_outgoing_moves(self, cursor, user, packing_id, name, value, arg,
+ context=None):
+ move_obj = self.pool.get('stock.move')
+ packing = self.browse(cursor, user, packing_id, context=context)
+ for act in value:
+ if act[0] == 'create':
+ if 'from_location' in act[1]:
+ if act[1]['from_location'] != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Outgoing Moves must ' \
+ 'have output location as source location!')
+ elif act[0] == 'write':
+ if 'from_location' in act[2]:
+ if act[2]['from_location'] != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Outgoing Moves must ' \
+ 'have output location as source location!')
+ elif act[0] == 'add':
+ move = move_obj.browse(cursor, user, act[1], context=context)
+ if move.from_location.id != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Outgoing Moves must ' \
+ 'have output location as source location!')
+ elif act[0] == 'set':
+ moves = move_obj.browse(cursor, user, act[1], context=context)
+ for move in moves:
+ if move.from_location.id != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Outgoing Moves must ' \
+ 'have output location as source location!')
+ self.write(cursor, user, packing_id, {
+ 'moves': value,
+ }, context=context)
+
+ def get_inventory_moves(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for packing in self.browse(cursor, user, ids, context=context):
+ res[packing.id] = []
+ for move in packing.moves:
+ if move.to_location.id == \
+ packing.warehouse.output_location.id:
+ res[packing.id].append(move.id)
+ return res
+
+ def set_inventory_moves(self, cursor, user, packing_id, name, value, arg,
+ context=None):
+ move_obj = self.pool.get('stock.move')
+ packing = self.browse(cursor, user, packing_id, context=context)
+ for act in value:
+ if act[0] == 'create':
+ if 'to_location' in act[1]:
+ if act[1]['to_location'] != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have output location as destination location!')
+ elif act[0] == 'write':
+ if 'to_location' in act[2]:
+ if act[2]['to_location'] != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have output location as destination location!')
+ elif act[0] == 'add':
+ move = move_obj.browse(cursor, user, act[1], context=context)
+ if move.to_location.id != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have output location as destination location!')
+ elif act[0] == 'set':
+ moves = move_obj.browse(cursor, user, act[1], context=context)
+ for move in moves:
+ if move.to_location.id != \
+ packing.warehouse.output_location.id:
+ raise ExceptORM('UserError', 'Inventory Moves must ' \
+ 'have output location as destination location!')
+ self.write(cursor, user, packing_id, {
+ 'moves': value,
+ }, context=context)
+
def set_state_assigned(self, cursor, user, packing_id, context=None):
self.write(cursor, user, packing_id, {'state':'assigned'},
context=context)
diff --git a/packing.xml b/packing.xml
index 50dafd226a..42c9fa9305 100644
--- a/packing.xml
+++ b/packing.xml
@@ -329,7 +329,7 @@
Received
function
- set_state_received()
+ set_state_received()
create_inventory_moves()