Warehouse-location fusion, WIP.

This commit is contained in:
Bertrand Chenal
2008-04-24 00:49:17 +02:00
parent bf62f6c8d0
commit 79e77b7ded
8 changed files with 154 additions and 203 deletions
-1
View File
@@ -24,7 +24,6 @@
#
##############################################################################
from warehouse import *
from location import *
from packing import *
from move import *
-1
View File
@@ -10,7 +10,6 @@
'partner', 'product'
],
'xml': [
'warehouse.xml',
'location.xml',
'move.xml',
'packing.xml',
+23 -13
View File
@@ -2,9 +2,12 @@
from trytond.osv import fields, OSV
STATES = {
'readonly': "active == False",
'readonly': "not active",
}
STATES_WH = {
'readonly': "(not active) or type != 'warehouse'",
'required': "type == 'warehouse' and active",
}
class Location(OSV):
"Stock Location"
_name = 'stock.location'
@@ -13,13 +16,26 @@ class Location(OSV):
name = fields.Char("Name", size=64, required=True, states=STATES,)
code = fields.Char("Code", size=32, states=STATES, select=True,)
active = fields.Boolean('Active', select=True)
usage = fields.Selection([('supplier', 'Supplier'),
address = fields.Many2One("partner.address", "Address", states=STATES_WH,)
type = fields.Selection([('supplier', 'Supplier'),
('customer', 'Customer'),
('inventory', 'Inventory'),
('procurement', 'Procurement'),
('warehouse', 'Warehouse'),
('storage', 'Storage'),
('production', 'Production')],
'Location type', states=STATES,)
warehouse = fields.Many2One("stock.warehouse", "Warehouse", select="1")
parent = fields.Many2One("stock.location", "Parent", select="1")
childs = fields.One2Many("stock.location", "parent", "Childs",)
input_location = fields.Many2One(
"stock.location", "Input", states=STATES_WH,
domain="[('type','=','storage')]",)
output_location = fields.Many2One(
"stock.location", "Output", states=STATES_WH,
domain="[('type','=','storage')]",)
storage_location = fields.Many2One(
"stock.location", "Storage", states=STATES_WH,
domain="[('type','=','storage')]")
# TODO: champ calcule vers product (retournant les product dispo)
# + context qui passe la location courante et permet de calculer
@@ -28,6 +44,9 @@ class Location(OSV):
def default_active(self, cursor, user, context=None):
return True
def default_type(self, cursor, user, context=None):
return 'storage'
def name_search(self, cursor, user, name, args=None, operator='ilike',
context=None, limit=80):
if not args:
@@ -107,12 +126,3 @@ class Location(OSV):
Location()
class Warehouse(OSV):
_name = "stock.warehouse"
_inherit = "stock.warehouse"
input_location = fields.Many2One("stock.location", "Input location", required=True,)
output_location = fields.Many2One("stock.location", "Output location", required=True,)
store_location = fields.Many2One("stock.location", "Default store location", required=True,)
Warehouse()
+74 -14
View File
@@ -1,6 +1,7 @@
<?xml version="1.0"?>
<tryton>
<data>
<menuitem name="Inventory Management" sequence="3" id="menu_stock"/>
<record model="ir.ui.view" id="location_view_form">
<field name="model">stock.location</field>
<field name="type">form</field>
@@ -11,17 +12,21 @@
<field name="name"/>
<label name="code"/>
<field name="code"/>
<label name="usage"/>
<field name="usage"/>
<label name="parent"/>
<field name="parent"/>
<label name="active"/>
<field name="active"/>
<label name="type"/>
<field name="type"/>
<newline/>
<label name="input_zone"/>
<field name="input_zone"/>
<label name="output_zone"/>
<field name="output_zone"/>
<label name="warehouse"/>
<field name="warehouse"/>
<label name="address"/>
<field name="address"/>
<label name="input_location"/>
<field name="input_location"/>
<label name="output_location"/>
<field name="output_location"/>
<label name="storage_location"/>
<field name="storage_location"/>
</form>
]]>
</field>
@@ -29,23 +34,40 @@
<record model="ir.ui.view" id="location_view_tree">
<field name="model">stock.location</field>
<field name="type">tree</field>
<field name="field_childs">childs</field>
<field name="arch" type="xml">
<![CDATA[
<tree string="locations">
<field name="name" select="1"/>
<field name="code" select="2"/>
<field name="usage" select="1"/>
<field name="input_zone" select="2"/>
<field name="output_zone" select="2"/>
<field name="warehouse" select="2"/>
<field name="type" select="1"/>
<field name="input_location" select="2"/>
<field name="output_location" select="2"/>
<field name="storage_location" select="2"/>
<field name="parent" select="2"/>
<field name="active" select="2"/>
</tree>
]]>
</field>
</record>
<record model="ir.action.act_window" id="act_location_form">
<record model="ir.action.act_window" id="act_location_tree">
<field name="name">Locations</field>
<field name="res_model">stock.location</field>
<field name="view_type">tree</field>
<field name="domain">[('parent', '=', False)]</field>
</record>
<record model="ir.action.act_window.view" id="act_location_tree_view">
<field name="sequence" eval="10"/>
<field name="view" ref="location_view_tree"/>
<field name="act_window" ref="act_location_tree"/>
</record>
<menuitem parent="menu_stock" sequence="1"
action="act_location_tree" id="menu_location_tree"/>
<record model="ir.action.act_window" id="act_location_form">
<field name="name">Edit Locations</field>
<field name="res_model">stock.location</field>
<field name="view_type">form</field>
</record>
<record model="ir.action.act_window.view" id="act_location_form_view1">
@@ -58,10 +80,17 @@
<field name="view" ref="location_view_form"/>
<field name="act_window" ref="act_location_form"/>
</record>
<menuitem parent="menu_stock" sequence="2"
<menuitem parent="menu_location_tree" sequence="1"
action="act_location_form" id="menu_location_form"/>
<!-- Model Access -->
<record model="res.group" id="group_stock_admin">
<field name="name">Stock administration</field>
</record>
<record model="res.user" id="res.user_admin">
<field name="groups" eval="[('add', ref('group_stock_admin'))]"/>
</record>
<record model="ir.model.access" id="access_location">
<field name="model" search="[('model', '=', 'stock.location')]"/>
<field name="perm_read" eval="True"/>
@@ -78,5 +107,36 @@
<field name="perm_unlink" eval="True"/>
</record>
<!-- Default locations -->
<record model="stock.location" id="location_input">
<field name="name">Input Zone</field>
<field name="code">IN</field>
<field name="type">storage</field>
</record>
<record model="stock.location" id="location_output">
<field name="name">Output Zone</field>
<field name="code">OUT</field>
<field name="type">storage</field>
</record>
<record model="stock.location" id="location_storage">
<field name="name">Storage Zone</field>
<field name="code">STO</field>
<field name="type">storage</field>
</record>
<record model="stock.location" id="location_warehouse">
<field name="name">Warehouse</field>
<field name="code">WH</field>
<field name="type">warehouse</field>
<field name="input_location" ref="location_input"/>
<field name="output_location" ref="location_output"/>
<field name="storage_location" ref="location_storage"/>
</record>
<!-- <record model="stock.location" id="location_storage"> -->
<!-- <field name="parent" ref="location_warehouse"/> -->
<!-- </record> -->
</data>
</tryton>
+49 -60
View File
@@ -20,12 +20,12 @@ class Move(OSV):
quantity = fields.Float(
"Quantity", digits=(12, 6), required=True,
states=STATES,)
from_location =fields.Many2One(
from_location = fields.Many2One(
"stock.location", "From Location", select=True, required=True,
states=STATES,)
states=STATES, domain="[('type', '!=', 'warehouse')]",)
to_location = fields.Many2One(
"stock.location", "To Location", select=True, required=True,
states=STATES,)
states=STATES,domain="[('type', '!=', 'warehouse')]",)
incoming_packing_in = fields.Many2One(
"stock.packing.in", "Supplier Packing", states=STATES, select=True)
inventory_packing_in = fields.Many2One(
@@ -95,59 +95,47 @@ class Move(OSV):
return True
def default_to_location(self, cursor, user, context=None):
if context and context.get('wh_incoming'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_incoming'], context=context)
return warehouse.input_location.id
if context and context.get('wh_inv_out'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_inv_out'], context=context)
return warehouse.output_location.id
if context and context.get('wh_inv_in'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_inv_in'], context=context)
return warehouse.store_location.id
return False
if context and context.get('warehouse') and context.get('type'):
wh_location = self.pool.get('stock.location').browse(
cursor, user, context['warehouse'], context=context)
field = {'inventory_in': 'storage_location',
'inventory_out': 'output_location',
'incoming': 'input_location',}.get(context['type'])
return field and wh_location[field].id or False
def default_from_location(self, cursor, user, context=None):
if context and context.get('wh_inv_in'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_inv_in'], context=context)
return warehouse.input_location.id
if context and context.get('wh_outgoing'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_outgoing'], context=context)
return warehouse.output_location.id
if context and context.get('wh_inv_out'):
warehouse = self.pool.get('stock.warehouse').browse(
cursor, user, context['wh_inv_out'], context=context)
return warehouse.store_location.id
return False
if context and context.get('warehouse') and context.get('type'):
wh_location = self.pool.get('stock.location').browse(
cursor, user, context['warehouse'], context=context)
field = {'inventory_in': 'input_location',
'inventory_out': 'storage_location',
'outgoing': 'output_location',}.get(context['type'])
return field and wh_location[field].id or False
def default_state(self, cursor, user, context=None):
if not context: return 'draft'
if 'pack_incoming_state' in context:
if context['pack_incoming_state'] == 'waiting':
return 'waiting'
if context['pack_incoming_state'] in ('received', 'done'):
return 'done'
if 'pack_inv_in_state' in context:
if context['pack_inv_in_state'] == 'received':
return 'waiting'
if context['pack_inv_in_state'] == 'done':
return 'done'
if 'pack_outgoing_state' in context:
if context['pack_outgoing_state'] in \
('waiting', 'assigned', 'ready'):
return 'waiting'
if context['pack_outgoing_state'] in 'done':
return 'done'
if 'pack_inv_out_state' in context:
if context['pack_inv_out_state'] == 'assigned':
return 'waiting'
if context['pack_inv_out_state'] == 'ready':
return 'done'
#TODO
# if not context: return 'draft'
# if 'pack_incoming_state' in context:
# if context['pack_incoming_state'] == 'waiting':
# return 'waiting'
# if context['pack_incoming_state'] in ('received', 'done'):
# return 'done'
# if 'pack_inv_in_state' in context:
# if context['pack_inv_in_state'] == 'received':
# return 'waiting'
# if context['pack_inv_in_state'] == 'done':
# return 'done'
# if 'pack_outgoing_state' in context:
# if context['pack_outgoing_state'] in \
# ('waiting', 'assigned', 'ready'):
# return 'waiting'
# if context['pack_outgoing_state'] in 'done':
# return 'done'
# if 'pack_inv_out_state' in context:
# if context['pack_inv_out_state'] == 'assigned':
# return 'waiting'
# if context['pack_inv_out_state'] == 'ready':
# return 'done'
return 'draft'
def on_change_product(self, cursor, user, ids, value, context=None):
@@ -217,7 +205,7 @@ class CreatePacking(Wizard):
move_obj = self.pool.get('stock.move')
packing_obj = self.pool.get('stock.packing.in')
warehouse_obj = self.pool.get('stock.warehouse')
location_obj = self.pool.get('stock.location')
moves = move_obj.browse(cursor, user, data['ids'], context=context)
# Collect moves by incoming location
@@ -237,25 +225,26 @@ class CreatePacking(Wizard):
moves_by_location[location].append(move.id)
# Fetch warehouse for these locations
warehouse_ids = warehouse_obj.search(
wh_location_ids = location_obj.search(
cursor, user,
[('input_location', 'in',
[l for l in moves_by_location])])
warehouses = warehouse_obj.browse(
[l for l in moves_by_location]),
('usage','=','warehouse')])
wh_locations = location_obj.browse(
cursor, user, warehouse_ids, context=context)
loc2wh = dict([( wh.input_location.id, wh.id) for wh in warehouses])
loc2wh = dict([( whl.input_location.id, whl.id) for whl in wh_locations])
packing_ids = []
for location, move_ids in moves_by_location.iteritems():
wh = loc2wh.get(location)
if not wh:
whl = loc2wh.get(location)
if not whl:
raise ExceptWizard(
'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': wh},
{'incoming_moves': [('set',move_ids)], 'warehouse': whl},
context=context)
packing_ids.append(pid)
+8 -7
View File
@@ -17,21 +17,21 @@ class PackingIn(OSV):
effective_date =fields.DateTime('Effective Date', readonly=True)
planned_date = fields.DateTime('Planned Date', readonly=True)
warehouse = fields.Many2One(
'stock.warehouse',"Warehouse", required=True, states=STATES,)
'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="{'wh_incoming': warehouse, 'pack_incoming_state': state}")
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="{'wh_inv_in': warehouse, 'pack_inv_in_state': state}")
context="{'warehouse': warehouse, 'packing_state': state, 'type':'inventory_in'}")
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)
def __init__(self):
super(PackingIn, self).__init__()
self._rpc_allowed += [
@@ -142,15 +142,16 @@ class PackingOut(OSV):
effective_date =fields.DateTime('Effective Date', readonly=True)
planned_date = fields.DateTime('Planned Date', readonly=True)
warehouse = fields.Many2One(
'stock.warehouse',"Warehouse", required=True, states=STATES,)
'stock.location',"Warehouse", required=True, states=STATES,
domain="[('type', '=', 'warehouse')]",)
outgoing_moves = fields.One2Many(
'stock.move', 'outgoing_packing_out', 'Outgoing Moves',
states=STATES,
context="{'wh_outgoing': warehouse, 'pack_outgoing_state': state}")
context="{'warehouse': warehouse, 'packing_state': state, 'type':'outgoing',}")
inventory_moves = fields.One2Many(
'stock.move', 'inventory_packing_out', 'Inventory Moves',
states={'readonly':"state not in ('assigned')",},
context="{'wh_inv_out': warehouse, 'pack_inv_out_state': state}")
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'),
-23
View File
@@ -1,23 +0,0 @@
"Wharehouse"
from trytond.osv import fields, OSV
STATES = {
'readonly': "active == False",
}
class Warehouse(OSV):
"Warehouse"
_name = 'stock.warehouse'
_order = 'name'
_description = __doc__
name = fields.Char("Name", size=64, required=True, select=True)
address = fields.Many2One("partner.address", "Address")
locations = fields.One2Many(
"stock.location", "warehouse", "Storage locations",)
active = fields.Boolean('Active', select=True)
def default_active(self, cursor, user, context=None):
return True
Warehouse()
-84
View File
@@ -1,84 +0,0 @@
<?xml version="1.0"?>
<tryton>
<data>
<menuitem name="Inventory Management" sequence="3" id="menu_stock"/>
<record model="ir.ui.view" id="warehouse_view_form">
<field name="model">stock.warehouse</field>
<field name="type">form</field>
<field name="arch" type="xml">
<![CDATA[
<form string="Warehouse">
<label name="name"/>
<field name="name"/>
<label name="address"/>
<field name="address"/>
<label name="input_location"/>
<field name="input_location"/>
<label name="output_location"/>
<field name="output_location"/>
<label name="store_location"/>
<field name="store_location"/>
<separator name="locations" colspan="4"/>
<field name="locations" colspan="4"/>
</form>
]]>
</field>
</record>
<record model="ir.ui.view" id="warehouse_view_tree">
<field name="model">stock.warehouse</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<![CDATA[
<tree string="Warehouses">
<field name="name"/>
<field name="address"/>
</tree>
]]>
</field>
</record>
<record model="ir.action.act_window" id="act_warehouse_form">
<field name="name">Warehouses</field>
<field name="res_model">stock.warehouse</field>
<field name="view_type">form</field>
</record>
<record model="ir.action.act_window.view" id="act_warehouse_form_view1">
<field name="sequence" eval="1"/>
<field name="view" ref="warehouse_view_tree"/>
<field name="act_window" ref="act_warehouse_form"/>
</record>
<record model="ir.action.act_window.view" id="act_warehouse_form_view2">
<field name="sequence" eval="2"/>
<field name="view" ref="warehouse_view_form"/>
<field name="act_window" ref="act_warehouse_form"/>
</record>
<menuitem parent="menu_stock" sequence="1"
action="act_warehouse_form" id="menu_warehouse_form"/>
<record model="res.group" id="group_stock_admin">
<field name="name">Stock administration</field>
</record>
<record model="res.user" id="res.user_admin">
<field name="groups" eval="[('add', ref('group_stock_admin'))]"/>
</record>
<record model="ir.model.access" id="access_warehouse">
<field name="model" search="[('model', '=', 'stock.warehouse')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
</record>
<record model="ir.model.access" id="access_stock_admin">
<field name="model" search="[('model', '=', 'stock.warehouse')]"/>
<field name="group" ref="group_stock_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
</data>
</tryton>