mirror of
https://gitlab.com/datalifeit/trytond-stock_product_category_location
synced 2023-12-14 04:33:11 +01:00
9a7f2e9227
This commit refs #21470
134 lines
4.5 KiB
Python
134 lines
4.5 KiB
Python
# The COPYRIGHT file at the top level of this repository contains the full
|
|
# copyright notices and license terms.
|
|
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.exceptions import UserError
|
|
from trytond.i18n import gettext
|
|
from sql.aggregate import Max
|
|
|
|
|
|
__all__ = ['ProductCategoryLocation', 'Location']
|
|
|
|
|
|
class ProductCategoryLocation(ModelSQL, ModelView):
|
|
"""Product Category Location"""
|
|
__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,
|
|
domain=[('type', '=', 'warehouse')],
|
|
states={
|
|
'invisible': Bool(
|
|
Eval('context', {}).get('current_location', None)),
|
|
'readonly': Bool(
|
|
Eval('context', {}).get('current_location', None)),
|
|
},
|
|
ondelete='CASCADE')
|
|
location = fields.Many2One('stock.location', 'Storage Location',
|
|
required=True, ondelete='CASCADE',
|
|
domain=[
|
|
('type', '=', 'storage'),
|
|
('parent', 'child_of', Eval('warehouse'))
|
|
], depends=['warehouse'])
|
|
sequence = fields.Integer('Sequence')
|
|
|
|
@staticmethod
|
|
def _compute_sequence_where(table, record):
|
|
return (
|
|
(table.category == record['category'])
|
|
& (table.warehouse == record['warehouse']))
|
|
|
|
@staticmethod
|
|
def _compute_sequence(table, record):
|
|
cursor = Transaction().connection.cursor()
|
|
seq_sel = table.select(
|
|
Max(table.sequence).as_('max_sequence'))
|
|
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
|
|
|
|
@classmethod
|
|
def create(cls, vlist):
|
|
vlist = [x.copy() for x in vlist]
|
|
for values in vlist:
|
|
if not values.get('sequence', None):
|
|
values['sequence'] = cls._compute_sequence(
|
|
cls.__table__(), values)
|
|
return super().create(vlist)
|
|
|
|
@classmethod
|
|
def default_warehouse(cls):
|
|
Location = Pool().get('stock.location')
|
|
|
|
loc_id = Transaction().context.get('current_location', None)
|
|
|
|
if loc_id:
|
|
loc = Location(loc_id)
|
|
if loc and loc.type == 'storage':
|
|
while not loc.parent.type == 'warehouse':
|
|
loc = loc.parent
|
|
return loc.parent.id
|
|
return None
|
|
|
|
def _get_unique_key(self):
|
|
return (self.category.id, self.location.id)
|
|
|
|
@classmethod
|
|
def validate(cls, records):
|
|
values = {}
|
|
for record in records:
|
|
_uq = record._get_unique_key()
|
|
if values.get(_uq):
|
|
raise UserError(gettext(
|
|
'stock_product_category_location.'
|
|
'msg_category_location_unique_key'))
|
|
values.setdefault(_uq, 1)
|
|
|
|
others = cls.search([('id', 'not in', list(map(int, records)))])
|
|
for other in others:
|
|
_uq = other._get_unique_key()
|
|
if values.get(_uq):
|
|
raise UserError(gettext(
|
|
'stock_product_category_location.'
|
|
'msg_category_location_unique_key'))
|
|
|
|
super().validate(records)
|
|
|
|
|
|
class Location(metaclass=PoolMeta):
|
|
__name__ = 'stock.location'
|
|
|
|
categories = fields.One2Many('stock.product.category.location',
|
|
'location', 'Categories',
|
|
states={
|
|
'invisible': Not(Equal(Eval('type'), 'storage'))
|
|
},
|
|
context={'current_location': Eval('id')})
|
|
wh_categories = fields.One2Many('stock.product.category.location',
|
|
'warehouse', 'Categories',
|
|
states={
|
|
'invisible': Not(Equal(Eval('type'), 'warehouse'))
|
|
},
|
|
context={'current_location': Eval('id')})
|
|
|
|
@classmethod
|
|
def view_attributes(cls):
|
|
return super().view_attributes() + [
|
|
('//page[@id="categories"]', 'states', {
|
|
'invisible': ~Eval('type').in_(['warehouse', 'storage'])})]
|
|
|
|
@classmethod
|
|
def copy(cls, records, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.setdefault('categories', None)
|
|
default.setdefault('wh_categories', None)
|
|
return super().copy(records, default=default)
|