268 lines
9.9 KiB
Python
268 lines
9.9 KiB
Python
# 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 ModelSQL, fields
|
|
from trytond.modules.company.model import CompanyValueMixin
|
|
from trytond.modules.product.product import TemplateFunction
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval
|
|
from trytond.transaction import Transaction
|
|
|
|
cost_price_warehouse = fields.Boolean(
|
|
"Cost Price per Warehouse",
|
|
help="Compute product cost price for each warehouse.")
|
|
|
|
|
|
class Configuration(metaclass=PoolMeta):
|
|
__name__ = 'product.configuration'
|
|
cost_price_warehouse = fields.MultiValue(cost_price_warehouse)
|
|
|
|
@classmethod
|
|
def default_cost_price_warehouse(cls, **pattern):
|
|
return cls.multivalue_model(
|
|
'cost_price_warehouse').default_cost_price_warehouse()
|
|
|
|
|
|
class ConfigurationCostPriceWarehouse(ModelSQL, CompanyValueMixin):
|
|
__name__ = 'product.configuration.cost_price_warehouse'
|
|
cost_price_warehouse = cost_price_warehouse
|
|
|
|
@classmethod
|
|
def default_cost_price_warehouse(cls):
|
|
return False
|
|
|
|
|
|
class Product(metaclass=PoolMeta):
|
|
__name__ = 'product.product'
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super().__setup__()
|
|
readonly = (
|
|
Eval('context', {}).get('cost_price_warehouse', False)
|
|
& ~Eval('context', {}).get('warehouse'))
|
|
if cls.cost_price.states['readonly']:
|
|
cls.cost_price.states['readonly'] |= readonly
|
|
else:
|
|
cls.cost_price.states['readonly'] = readonly
|
|
|
|
def multivalue_records(self, field):
|
|
Value = self.multivalue_model(field)
|
|
records = super().multivalue_records(field)
|
|
if issubclass(Value, CostPrice):
|
|
# Sort to get record with empty warehouse at the end
|
|
records = sorted(records, key=lambda r: r.warehouse is None)
|
|
return records
|
|
|
|
def get_multivalue(self, name, **pattern):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
if not isinstance(self._fields[name], TemplateFunction):
|
|
Value = self.multivalue_model(name)
|
|
if issubclass(Value, CostPrice) and context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
pattern.setdefault('warehouse', context.get('warehouse'))
|
|
return super().get_multivalue(name, **pattern)
|
|
|
|
def set_multivalue(self, name, value, save=True, **pattern):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
Value = self.multivalue_model(name)
|
|
if issubclass(Value, CostPrice) and context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
pattern.setdefault('warehouse', context.get('warehouse'))
|
|
if not value and not pattern.get('warehouse'):
|
|
return []
|
|
return super().set_multivalue(name, value, save=save, **pattern)
|
|
|
|
@classmethod
|
|
def _domain_moves_cost(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
domain = super()._domain_moves_cost()
|
|
if context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
warehouse = context.get('warehouse')
|
|
domain = [
|
|
domain,
|
|
['OR',
|
|
('from_location', 'child_of', warehouse, 'parent'),
|
|
('from_location.cost_warehouse', '=', warehouse),
|
|
('to_location', 'child_of', warehouse, 'parent'),
|
|
('to_location.cost_warehouse', '=', warehouse),
|
|
],
|
|
]
|
|
return domain
|
|
|
|
@classmethod
|
|
def _domain_in_moves_cost(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
domain = super()._domain_in_moves_cost()
|
|
if context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
warehouse = context.get('warehouse')
|
|
domain = ['OR',
|
|
domain,
|
|
[
|
|
('from_location.type', '=', 'storage'),
|
|
('to_location.type', '=', 'storage'),
|
|
('from_location', 'not child_of', warehouse, 'parent'),
|
|
['OR',
|
|
('from_location.cost_warehouse', '!=', warehouse),
|
|
('from_location.cost_warehouse', '=', None),
|
|
],
|
|
['OR',
|
|
('to_location', 'child_of', warehouse, 'parent'),
|
|
('to_location.cost_warehouse', '=', warehouse),
|
|
],
|
|
]
|
|
]
|
|
return domain
|
|
|
|
@classmethod
|
|
def _domain_out_moves_cost(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
domain = super()._domain_out_moves_cost()
|
|
if context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
warehouse = context.get('warehouse')
|
|
domain = ['OR',
|
|
domain,
|
|
[
|
|
('from_location.type', '=', 'storage'),
|
|
('to_location.type', '=', 'storage'),
|
|
('to_location', 'not child_of', warehouse, 'parent'),
|
|
['OR',
|
|
('to_location.cost_warehouse', '!=', warehouse),
|
|
('to_location.cost_warehouse', '=', None),
|
|
],
|
|
['OR',
|
|
('from_location', 'child_of', warehouse, 'parent'),
|
|
('from_location.cost_warehouse', '=', warehouse),
|
|
],
|
|
]
|
|
]
|
|
return domain
|
|
|
|
@classmethod
|
|
def _domain_storage_quantity(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
context = Transaction().context
|
|
domain = super()._domain_storage_quantity()
|
|
if context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
warehouse = context.get('warehouse')
|
|
domain = [
|
|
domain,
|
|
['OR',
|
|
('parent', 'child_of', warehouse),
|
|
('cost_warehouse', '=', warehouse),
|
|
],
|
|
]
|
|
return domain
|
|
|
|
@classmethod
|
|
def default_cost_price(cls, **pattern):
|
|
context = Transaction().context
|
|
default = super().default_cost_price()
|
|
if (context.get('cost_price_warehouse')
|
|
and not pattern.get('warehouse', context.get('warehouse'))):
|
|
default = None
|
|
return default
|
|
|
|
|
|
class CostPrice(metaclass=PoolMeta):
|
|
__name__ = 'product.cost_price'
|
|
warehouse = fields.Many2One(
|
|
'stock.location', "Warehouse", ondelete='RESTRICT',
|
|
domain=[
|
|
('type', '=', 'warehouse'),
|
|
],
|
|
states={
|
|
'required': Eval('warehouse_required', False),
|
|
})
|
|
warehouse_required = fields.Function(fields.Boolean(
|
|
"Warehouse Required"), 'get_warehouse_required')
|
|
|
|
@classmethod
|
|
def get_warehouse_required(cls, records, name):
|
|
return {r.id: r.company.cost_price_warehouse for r in records}
|
|
|
|
|
|
class CostPriceRevision(metaclass=PoolMeta):
|
|
__name__ = 'product.cost_price.revision'
|
|
warehouse = fields.Many2One(
|
|
'stock.location', "Warehouse", ondelete='RESTRICT',
|
|
domain=[
|
|
('type', '=', 'warehouse'),
|
|
],
|
|
states={
|
|
'required': Eval('warehouse_required', False),
|
|
})
|
|
warehouse_required = fields.Function(fields.Boolean(
|
|
"Warehouse Required"), 'get_warehouse_required')
|
|
|
|
@classmethod
|
|
def default_warehouse(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
company_id = cls.default_company()
|
|
if company_id is not None and company_id >= 0:
|
|
company = Company(company_id)
|
|
if company.cost_price_warehouse:
|
|
return Transaction().context.get('warehouse')
|
|
|
|
@classmethod
|
|
def get_warehouse_required(cls, records, name):
|
|
return {r.id: r.company.cost_price_warehouse for r in records}
|
|
|
|
@classmethod
|
|
def _get_for_product_domain(cls):
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
domain = super()._get_for_product_domain()
|
|
context = Transaction().context
|
|
if context.get('company'):
|
|
company = Company(context['company'])
|
|
if company.cost_price_warehouse:
|
|
domain = [
|
|
domain,
|
|
('warehouse', '=', context.get('warehouse')),
|
|
]
|
|
return domain
|
|
|
|
|
|
class ModifyCostPrice(metaclass=PoolMeta):
|
|
__name__ = 'product.modify_cost_price'
|
|
|
|
def get_revision(self, Revision):
|
|
revision = super().get_revision(Revision)
|
|
if revision.company.cost_price_warehouse:
|
|
revision.warehouse = Transaction().context.get('warehouse')
|
|
return revision
|
|
|
|
|
|
class ProductCostHistory(metaclass=PoolMeta):
|
|
__name__ = 'product.product.cost_history'
|
|
|
|
@classmethod
|
|
def _non_moves_clause(cls, history_table, user):
|
|
clause = super()._non_moves_clause(history_table, user)
|
|
if user.company and user.company.cost_price_warehouse:
|
|
warehouse_id = user.warehouse.id if user.warehouse else None
|
|
clause &= history_table.warehouse == warehouse_id
|
|
return clause
|