mirror of
https://gitlab.com/datalifeit/trytond-stock_product_category_location
synced 2023-12-14 04:33:11 +01:00
parent
882a88ce58
commit
a9c9bd921a
|
@ -3,8 +3,8 @@ msgid ""
|
|||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "error:stock.product.category.location:"
|
||||
msgid "Category, location and process must be unique."
|
||||
msgstr "Categoria, ubicación y proceso deben ser únicos."
|
||||
msgid "Category and location must be unique."
|
||||
msgstr "Categoria y ubicación deben ser únicos."
|
||||
|
||||
msgctxt "field:product.category,locations:"
|
||||
msgid "Default Locations"
|
||||
|
@ -34,10 +34,6 @@ msgctxt "field:stock.product.category.location,location:"
|
|||
msgid "Storage Location"
|
||||
msgstr "Ubicación de almacenamiento"
|
||||
|
||||
msgctxt "field:stock.product.category.location,process:"
|
||||
msgid "Process"
|
||||
msgstr "Proceso"
|
||||
|
||||
msgctxt "field:stock.product.category.location,rec_name:"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
|
21
location.py
21
location.py
|
@ -4,20 +4,19 @@ from trytond.model import ModelView, ModelSQL, fields
|
|||
from trytond.pyson import Eval, Bool, Not, Equal
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.modules.business_process.process import BusinessProcessMixin
|
||||
from sql.aggregate import Max
|
||||
|
||||
|
||||
__all__ = ['ProductCategoryLocation', 'Location']
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
|
||||
class ProductCategoryLocation(ModelSQL, ModelView, BusinessProcessMixin):
|
||||
class ProductCategoryLocation(ModelSQL, ModelView):
|
||||
"""
|
||||
Product Category Location
|
||||
It defines the default storage location by warehouse for a product category.
|
||||
"""
|
||||
__name__ = 'stock.product.category.location'
|
||||
|
||||
category = fields.Many2One(
|
||||
'product.category', 'Category', required=True, select=True, ondelete='CASCADE')
|
||||
warehouse = fields.Many2One('stock.location', 'Warehouse', required=True,
|
||||
|
@ -37,17 +36,19 @@ class ProductCategoryLocation(ModelSQL, ModelView, BusinessProcessMixin):
|
|||
def __setup__(cls):
|
||||
super(ProductCategoryLocation, cls).__setup__()
|
||||
cls._error_messages.update({
|
||||
'unique_key': 'Category, location and process must be unique.'})
|
||||
'unique_key': 'Category and location must be unique.'})
|
||||
|
||||
@staticmethod
|
||||
def _compute_sequence_where(table, record):
|
||||
return ((table.category == record['category']) &
|
||||
(table.warehouse == record['warehouse']))
|
||||
|
||||
@staticmethod
|
||||
def _compute_sequence(table, record):
|
||||
cursor = Transaction().cursor
|
||||
seq_sel = table.select(
|
||||
Max(table.sequence).as_('max_sequence'))
|
||||
seq_sel.where = (
|
||||
(table.category == record['category']) &
|
||||
(table.warehouse == record['warehouse']) &
|
||||
(table.process == record['process']))
|
||||
seq_sel.where = ProductCategoryLocation._compute_sequence_where(table, record)
|
||||
cursor.execute(*seq_sel)
|
||||
rec = cursor.fetchall()[0]
|
||||
return rec[0] + 1 if rec[0] else 1
|
||||
|
@ -75,8 +76,7 @@ class ProductCategoryLocation(ModelSQL, ModelView, BusinessProcessMixin):
|
|||
return None
|
||||
|
||||
def _get_unique_key(self):
|
||||
return (self.category.id, self.location.id,
|
||||
self.process.id if self.process else None)
|
||||
return (self.category.id, self.location.id)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, records):
|
||||
|
@ -98,6 +98,7 @@ class ProductCategoryLocation(ModelSQL, ModelView, BusinessProcessMixin):
|
|||
|
||||
class Location:
|
||||
__name__ = 'stock.location'
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
categories = fields.One2Many('stock.product.category.location', 'location', 'Categories',
|
||||
states={
|
||||
|
|
34
product.py
34
product.py
|
@ -1,39 +1,39 @@
|
|||
# The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.model import fields
|
||||
from trytond.pyson import Eval
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
|
||||
__all__ = ['Category']
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
|
||||
class Category:
|
||||
__name__ = 'product.category'
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
locations = fields.One2Many(
|
||||
'stock.product.category.location', 'category', 'Default Locations')
|
||||
default_location = fields.Function(fields.Many2One('stock.location', 'Default location'),
|
||||
'get_default_location')
|
||||
|
||||
def get_default_location(self, warehouse=None,
|
||||
process=None,
|
||||
location_type='storage'):
|
||||
def get_default_location(self, **kwargs):
|
||||
pool = Pool()
|
||||
Location = pool.get('stock.product.category.location')
|
||||
|
||||
process_ids = [None]
|
||||
if process:
|
||||
process_ids.append(process.id)
|
||||
_domain = [('category', '=', self.id),
|
||||
('location.type', '=', location_type),
|
||||
('process', 'in', process_ids)]
|
||||
if warehouse:
|
||||
_domain.append(('warehouse', '=', warehouse.id))
|
||||
locations = Location.search(_domain,
|
||||
order=[('process', 'DESC'),
|
||||
('sequence', 'ASC')],
|
||||
limit=2)
|
||||
_domain = self._get_default_location_domain(**kwargs)
|
||||
locations = Location.search(
|
||||
_domain, order=self._get_default_location_order(),
|
||||
limit=2)
|
||||
if locations:
|
||||
return locations[0].location.id
|
||||
return None
|
||||
|
||||
def _get_default_location_domain(self, **kwargs):
|
||||
_domain = [('category', '=', self.id),
|
||||
('location.type', '=', kwargs.get('location_type', 'storage'))]
|
||||
if kwargs.get('warehouse', None):
|
||||
_domain.append(('warehouse', '=', kwargs['warehouse'].id))
|
||||
return _domain
|
||||
|
||||
@staticmethod
|
||||
def _get_default_location_order():
|
||||
return [('sequence', 'ASC')]
|
||||
|
|
|
@ -19,7 +19,6 @@ class StockProductCategoryLocationTestCase(ModuleTestCase):
|
|||
self.location = POOL.get('stock.location')
|
||||
self.category = POOL.get('product.category')
|
||||
self.cat_loc = POOL.get('stock.product.category.location')
|
||||
self.process = POOL.get('business.process')
|
||||
|
||||
def test0010_add_category_default_location(self):
|
||||
"""Add the category default location for a warehouse"""
|
||||
|
@ -30,28 +29,26 @@ class StockProductCategoryLocationTestCase(ModuleTestCase):
|
|||
cat_loc_rec = {
|
||||
'category': new_cat.id,
|
||||
'warehouse': storage.parent.id,
|
||||
'location': storage.id,
|
||||
'process': None
|
||||
'location': storage.id
|
||||
}
|
||||
self.cat_loc.create([cat_loc_rec])
|
||||
transaction.cursor.commit()
|
||||
|
||||
def test0020category_location_process_unique(self):
|
||||
def test0020category_location_unique(self):
|
||||
"""Check unique error"""
|
||||
|
||||
with Transaction().start(DB_NAME, USER, context=CONTEXT) as transaction:
|
||||
with Transaction().start(DB_NAME, USER, context=CONTEXT):
|
||||
storage, = self.location.search([('code', '=', 'STO')])
|
||||
new_cat, = self.category.search([('name', '=', 'CAT1')])
|
||||
cat_loc_rec = {
|
||||
'category': new_cat.id,
|
||||
'warehouse': storage.parent.id,
|
||||
'location': storage.id,
|
||||
'process': None
|
||||
'location': storage.id
|
||||
}
|
||||
with self.assertRaises(UserError) as cm:
|
||||
self.cat_loc.create([cat_loc_rec])
|
||||
self.assertEqual(
|
||||
cm.exception.message, 'Category, location and process must be unique.')
|
||||
cm.exception.message, 'Category and location must be unique.')
|
||||
|
||||
|
||||
def suite():
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[tryton]
|
||||
version=3.6.1
|
||||
depends:
|
||||
business_process
|
||||
ir
|
||||
res
|
||||
stock_location_notebook
|
||||
|
|
|
@ -8,6 +8,4 @@
|
|||
<field name="warehouse"/>
|
||||
<label name="location"/>
|
||||
<field name="location"/>
|
||||
<label name="process"/>
|
||||
<field name="process" widget="selection"/>
|
||||
</form>
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
<tree string="Category Locations" editable="bottom">
|
||||
<field name="category"/>
|
||||
<field name="location"/>
|
||||
<field name="process" widget="selection"/>
|
||||
</tree>
|
|
@ -5,6 +5,5 @@
|
|||
<field name="category"/>
|
||||
<field name="warehouse"/>
|
||||
<field name="location"/>
|
||||
<field name="process" widget="selection"/>
|
||||
<field name="sequence" tree_invisible="1"/>
|
||||
</tree>
|
||||
|
|
Loading…
Reference in a new issue