- Reduce move columns to have only one columns that link to packing in/out

- Add some constraints on move
- simplify creation of inventory move for packing in and simplify overriding
  that will add field on move
This commit is contained in:
Cédric Krier committed 2008-05-07 18:04:25 +02:00
1 parent a46dc8aaf5
commit b534d12db1
4 files changed
+278 -170

No files matched your search

+23 -69
View File
@@ -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()
+1 -20
View File
@@ -110,9 +110,7 @@
<field name="name">Moves from suppliers to proceed</field>
<field name="res_model">stock.move</field>
<field name="view_type">form</field>
<field name="domain">[('from_location.type', '=', 'supplier'),
('state','in',['draft','waiting']),('incoming_packing_in','=',False),
('inventory_packing_in','=',False)]</field>
<field name="domain">[('from_location.type', '=', 'supplier'), ('state','in',['draft','waiting']), ('_packing_in','=',False)]</field>
</record>
<record model="ir.action.act_window.view"
id="act_move_form_supp_proceed_view1">
@@ -177,22 +175,6 @@
action="act_move_form_cust_proceed"
id="menu_move_form_cust_proceed"/>
<record model="ir.ui.view" id="packing_create_warn_view_form">
<field name="model">stock.move.create_packing.warn</field>
<field name="type">form</field>
<field name="arch" type="xml">
<![CDATA[
<form string="Create packing" col="2">
<image name="gtk-dialog-info"/>
<label string="Moves already in a shipment will be
ignored."/>
</form>
]]>
</field>
</record>
<record model="ir.action.wizard" id="act_create_packing">
<field name="name">Create Packing</field>
<field name="wiz_name">stock.move.create_packing</field>
@@ -204,6 +186,5 @@
<field name="action" ref="act_create_packing"/>
</record>
</data>
</tryton>
+253 -80
View File
@@ -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)
+1 -1
View File
@@ -329,7 +329,7 @@
<field name="name">Received</field>
<field name="kind">function</field>
<field name="workflow" ref="wkf_packingin"/>
<field name="action">set_state_received()</field>
<field name="action">set_state_received()&#10;create_inventory_moves()</field>
</record>
<record model="workflow.transition"