diff --git a/__init__.py b/__init__.py
index 559b845427..166b1bb5cd 100644
--- a/__init__.py
+++ b/__init__.py
@@ -16,6 +16,7 @@ def register():
Pool.register(
Location,
Party,
+ PartyLocation,
ProductsByLocationsContext,
LocationLeadTime,
Move,
@@ -38,6 +39,8 @@ def register():
Inventory,
InventoryLine,
Configuration,
+ ConfigurationSequence,
+ ConfigurationLocation,
module='stock', type_='model')
Pool.register(
AssignShipmentOut,
diff --git a/configuration.py b/configuration.py
index 956b76e758..3d541068bc 100644
--- a/configuration.py
+++ b/configuration.py
@@ -1,51 +1,214 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
-from trytond.model import ModelView, ModelSQL, ModelSingleton, fields
+from trytond import backend
+from trytond.model import (ModelView, ModelSQL, ModelSingleton, ValueMixin,
+ fields)
+from trytond.pool import Pool
from trytond.pyson import Eval
+from trytond.tools.multivalue import migrate_property
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
-__all__ = ['Configuration']
+__all__ = ['Configuration', 'ConfigurationSequence', 'ConfigurationLocation']
+sequences = ['shipment_in_sequence', 'shipment_in_return_sequence',
+ 'shipment_out_sequence', 'shipment_out_return_sequence',
+ 'shipment_internal_sequence', 'inventory_sequence']
+shipment_internal_transit = fields.Many2One(
+ 'stock.location', "Internal Shipment Transit", required=True,
+ domain=[
+ ('type', '=', 'storage'),
+ ])
-class Configuration(ModelSingleton, ModelSQL, ModelView):
+def default_func(field_name):
+ @classmethod
+ def default(cls, **pattern):
+ return getattr(
+ cls.multivalue_model(field_name),
+ 'default_%s' % field_name, lambda: None)()
+ return default
+
+
+def default_sequence(name):
+ @classmethod
+ def default(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ return ModelData.get_id('stock', name)
+ return default
+
+
+class Configuration(
+ ModelSingleton, ModelSQL, ModelView, CompanyMultiValueMixin):
'Stock Configuration'
__name__ = 'stock.configuration'
- shipment_in_sequence = fields.Property(fields.Many2One('ir.sequence',
- 'Supplier Shipment Sequence', domain=[
+ shipment_in_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Supplier Shipment Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.shipment.in'),
- ], required=True))
- shipment_in_return_sequence = fields.Property(fields.Many2One(
- 'ir.sequence', 'Supplier Return Shipment Sequence', domain=[
+ ]))
+ shipment_in_return_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Supplier Return Shipment Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.shipment.in.return'),
- ], required=True))
- shipment_out_sequence = fields.Property(fields.Many2One('ir.sequence',
- 'Customer Shipment Sequence', domain=[
+ ]))
+ shipment_out_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Customer Shipment Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.shipment.out'),
- ], required=True))
- shipment_out_return_sequence = fields.Property(fields.Many2One(
- 'ir.sequence', 'Customer Return Shipment Sequence', domain=[
+ ]))
+ shipment_out_return_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Customer Return Shipment Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.shipment.out.return'),
- ], required=True))
- shipment_internal_sequence = fields.Property(fields.Many2One(
- 'ir.sequence', 'Internal Shipment Sequence', domain=[
+ ]))
+ shipment_internal_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Internal Shipment Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.shipment.internal'),
- ], required=True))
- shipment_internal_transit = fields.Property(fields.Many2One(
- 'stock.location', 'Internal Shipment Transit', domain=[
- ('type', '=', 'storage'),
- ], required=True))
- inventory_sequence = fields.Property(fields.Many2One(
- 'ir.sequence', 'Inventory Sequence', domain=[
+ ]))
+ inventory_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Inventory Sequence", required=True,
+ domain=[
('company', 'in',
[Eval('context', {}).get('company', -1), None]),
('code', '=', 'stock.inventory'),
- ], required=True))
+ ]))
+ shipment_internal_transit = fields.MultiValue(shipment_internal_transit)
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in sequences:
+ return pool.get('stock.configuration.sequence')
+ if field == 'shipment_internal_transit':
+ return pool.get('stock.configuration.location')
+ return super(Configuration, cls).multivalue_model(field)
+
+ default_shipment_in_sequence = default_func('shipment_in_sequence')
+ default_shipment_in_return_sequence = default_func(
+ 'shipment_in_return_sequence')
+ default_shipment_out_sequence = default_func('shipment_out_sequence')
+ default_shipment_out_return_sequence = default_func(
+ 'shipment_out_return_sequence')
+ default_shipment_internal_sequence = default_func(
+ 'shipment_internal_sequence')
+ default_inventory_sequence = default_func('inventory_sequence')
+ default_shipment_internal_transit = default_func(
+ 'shipment_internal_transit')
+
+
+class ConfigurationSequence(ModelSQL, CompanyValueMixin):
+ "Stock Configuration Sequence"
+ __name__ = 'stock.configuration.sequence'
+ shipment_in_sequence = fields.Many2One(
+ 'ir.sequence', "Supplier Shipment Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.shipment.in'),
+ ],
+ depends=['company'])
+ shipment_in_return_sequence = fields.Many2One(
+ 'ir.sequence', "Supplier Return Shipment Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.shipment.in.return'),
+ ],
+ depends=['company'])
+ shipment_out_sequence = fields.Many2One(
+ 'ir.sequence', "Customer Shipment Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.shipment.out'),
+ ],
+ depends=['company'])
+ shipment_out_return_sequence = fields.Many2One(
+ 'ir.sequence', "Customer Return Shipment Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.shipment.out.return'),
+ ],
+ depends=['company'])
+ shipment_internal_sequence = fields.Many2One(
+ 'ir.sequence', "Internal Shipment Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.shipment.internal'),
+ ],
+ depends=['company'])
+ inventory_sequence = fields.Many2One(
+ 'ir.sequence', "Inventory Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('code', '=', 'stock.inventory'),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def __register__(cls, module_name):
+ TableHandler = backend.get('TableHandler')
+ exist = TableHandler.table_exist(cls._table)
+
+ super(ConfigurationSequence, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.extend(sequences)
+ value_names.extend(sequences)
+ fields.append('company')
+ migrate_property(
+ 'stock.configuration', field_names, cls, value_names,
+ fields=fields)
+
+ default_shipment_in_sequence = default_sequence('sequence_shipment_in')
+ default_shipment_in_return_sequence = default_sequence(
+ 'sequence_shipment_in_return')
+ default_shipment_out_sequence = default_sequence('sequence_shipment_out')
+ default_shipment_out_return_sequence = default_sequence(
+ 'sequence_shipment_out_return')
+ default_shipment_internal_sequence = default_sequence(
+ 'sequence_shipment_internal')
+ default_inventory_sequence = default_sequence('sequence_inventory')
+
+
+class ConfigurationLocation(ModelSQL, ValueMixin):
+ "Stock Configuration Location"
+ __name__ = 'stock.configuration.location'
+ shipment_internal_transit = shipment_internal_transit
+
+ @classmethod
+ def __register__(cls, module_name):
+ TableHandler = backend.get('TableHandler')
+ exist = TableHandler.table_exist(cls._table)
+
+ super(ConfigurationLocation, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('shipment_internal_transit')
+ value_names.append('shipment_internal_transit')
+ migrate_property(
+ 'stock.configuration', field_names, cls, value_names,
+ fields=fields)
+
+ @classmethod
+ def default_shipment_internal_transit(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ return ModelData.get_id('stock', 'location_transit')
diff --git a/configuration.xml b/configuration.xml
index bf9a307ce0..02ff9c09f4 100644
--- a/configuration.xml
+++ b/configuration.xml
@@ -40,44 +40,4 @@ this repository contains the full copyright notices and license terms. -->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/location.py b/location.py
index 0a3b2194b8..f4aa88c35c 100644
--- a/location.py
+++ b/location.py
@@ -3,15 +3,16 @@
import datetime
from decimal import Decimal
-from trytond.model import ModelView, ModelSQL, MatchMixin, fields, \
- sequence_ordered
+from trytond.model import (ModelView, ModelSQL, MatchMixin, ValueMixin, fields,
+ sequence_ordered)
from trytond import backend
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
from trytond.tools import grouped_slice
+from trytond.tools.multivalue import migrate_property
-__all__ = ['Location', 'Party', 'ProductsByLocationsContext',
+__all__ = ['Location', 'Party', 'PartyLocation', 'ProductsByLocationsContext',
'LocationLeadTime']
STATES = {
@@ -396,17 +397,78 @@ class Location(ModelSQL, ModelView):
return res
+supplier_location = fields.Many2One(
+ 'stock.location', "Supplier Location", domain=[('type', '=', 'supplier')],
+ help='The default source location when receiving products from the party.')
+customer_location = fields.Many2One(
+ 'stock.location', "Customer Location", domain=[('type', '=', 'customer')],
+ help='The default destination location when sending products to the party.'
+ )
+
+
class Party:
__metaclass__ = PoolMeta
__name__ = 'party.party'
- supplier_location = fields.Property(fields.Many2One('stock.location',
- 'Supplier Location', domain=[('type', '=', 'supplier')],
- help='The default source location when receiving products from the '
- 'party.'))
- customer_location = fields.Property(fields.Many2One('stock.location',
- 'Customer Location', domain=[('type', '=', 'customer')],
- help='The default destination location when sending products to the '
- 'party.'))
+ supplier_location = fields.MultiValue(supplier_location)
+ customer_location = fields.MultiValue(customer_location)
+ locations = fields.One2Many(
+ 'party.party.location', 'party', "Locations")
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {'supplier_location', 'customer_location'}:
+ return pool.get('party.party.location')
+ return super(Party, cls).multivalue_model(field)
+
+ @classmethod
+ def default_supplier_location(cls, **pattern):
+ return cls.multivalue_model(
+ 'supplier_location').default_supplier_location()
+
+ @classmethod
+ def default_customer_location(cls, **pattern):
+ return cls.multivalue_model(
+ 'customer_location').default_customer_location()
+
+
+class PartyLocation(ModelSQL, ValueMixin):
+ "Party Location"
+ __name__ = 'party.party.location'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE', select=True)
+ supplier_location = supplier_location
+ customer_location = customer_location
+
+ @classmethod
+ def __register__(cls, module_name):
+ TableHandler = backend.get('TableHandler')
+ exist = TableHandler.table_exist(cls._table)
+
+ super(PartyLocation, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.extend(['supplier_location', 'customer_location'])
+ value_names.extend(['supplier_location', 'customer_location'])
+ migrate_property(
+ 'party.party', field_names, cls, value_names,
+ parent='party', fields=fields)
+
+ @classmethod
+ def default_supplier_location(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ return ModelData.get_id('stock', 'location_supplier')
+
+ @classmethod
+ def default_customer_location(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ return ModelData.get_id('stock', 'location_customer')
class ProductsByLocationsContext(ModelView):
diff --git a/location.xml b/location.xml
index ed7fbaac09..dd3edd616c 100644
--- a/location.xml
+++ b/location.xml
@@ -215,25 +215,5 @@ this repository contains the full copyright notices and license terms. -->
Transit
storage
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/shipment.py b/shipment.py
index 8e59e65900..e3945a6fea 100644
--- a/shipment.py
+++ b/shipment.py
@@ -2165,7 +2165,7 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
pool = Pool()
Config = pool.get('stock.configuration')
if self.planned_date != self.planned_start_date:
- return Config(1).shipment_internal_transit.id
+ return Config(1).get_multivalue('shipment_internal_transit').id
@fields.depends('planned_date', 'from_location', 'to_location')
def on_change_with_planned_start_date(self, pattern=None):