120 lines
4.6 KiB
Python
120 lines
4.6 KiB
Python
# This file is part of sale_pos module for Tryton.
|
|
# The COPYRIGHT file at the top level of this repository contains
|
|
# the full copyright notices and license terms.
|
|
from decimal import Decimal
|
|
|
|
from trytond.model import fields, ModelSQL, DeactivableMixin
|
|
from trytond.pool import PoolMeta, Pool
|
|
from trytond.modules.product import price_digits
|
|
from trytond.exceptions import UserError
|
|
from trytond.i18n import gettext
|
|
from trytond.transaction import Transaction
|
|
from trytond.modules.company.model import CompanyValueMixin
|
|
|
|
|
|
def round_num(value):
|
|
return Decimal(str(round(value, 4)))
|
|
|
|
|
|
class Configuration(metaclass=PoolMeta):
|
|
__name__ = 'product.configuration'
|
|
|
|
code_required = fields.MultiValue(
|
|
fields.Boolean(
|
|
"Code Required",
|
|
help="If code required and product dont have secuence and is good can not duplicate product"))
|
|
|
|
@classmethod
|
|
def multivalue_model(cls, field):
|
|
pool = Pool()
|
|
if field in 'code_required':
|
|
return pool.get('account.configuration.code_required')
|
|
return super().multivalue_model(field)
|
|
|
|
|
|
class ConfigurationCodeRequired(ModelSQL, CompanyValueMixin):
|
|
"Account Configuration Code Required"
|
|
__name__ = 'account.configuration.code_required'
|
|
|
|
code_required = fields.Boolean("Default Code Required")
|
|
|
|
|
|
class Product(metaclass=PoolMeta):
|
|
__name__ = 'product.product'
|
|
extra_tax = fields.Numeric('Extra Tax', digits=(16, 2))
|
|
last_cost = fields.Numeric('Last Cost', digits=price_digits,
|
|
help='Last purchase price')
|
|
sale_price_taxed = fields.Function(fields.Numeric('Sale Price Taxed',
|
|
digits=(16, 4)), 'get_sale_price_taxed')
|
|
cost_price_taxed = fields.Function(fields.Numeric('Cost Price Taxed',
|
|
digits=(16, 4)), 'get_cost_price_taxed')
|
|
|
|
@classmethod
|
|
def get_prices_taxed(cls, id_, cost_price, sale_price, sale_taxes):
|
|
product, = cls.browse([id_])
|
|
cost_price = product.get_cost_price_taxed(value=cost_price)
|
|
if sale_taxes:
|
|
sale_price = product.get_sale_price_taxed(value=sale_price)
|
|
return cost_price, sale_price
|
|
|
|
def get_cost_price_taxed(self, name=None, value=None):
|
|
res = value if value is not None else (self.cost_price)
|
|
taxes_used = self.account_category.supplier_taxes_used
|
|
taxes_used = [t for t in taxes_used if (t.type == 'percentage' and t.rate >= 0) or t.type == 'fixed']
|
|
Tax = Pool().get('account.tax')
|
|
tax_list = Tax.compute(taxes_used, res, 1)
|
|
extra_tax = self.extra_tax or 0
|
|
tax_amount = sum([t['amount'] for t in tax_list], Decimal('0.0')) + extra_tax
|
|
res = res + tax_amount
|
|
return round_num(res)
|
|
|
|
def get_sale_price_taxed(self, name=None, value=None):
|
|
res = value if value is not None else self.list_price
|
|
Tax = Pool().get('account.tax')
|
|
tax_list = Tax.compute(self.account_category.customer_taxes_used,
|
|
res, 1)
|
|
extra_tax = self.extra_tax or 0
|
|
tax_amount = sum([t['amount'] for t in tax_list], Decimal('0.0')) + extra_tax
|
|
res = res + tax_amount
|
|
return round_num(res)
|
|
|
|
|
|
class Template(metaclass=PoolMeta):
|
|
__name__ = 'product.template'
|
|
# remove field this is on module sale_pos_frontend
|
|
# sale_price_w_tax = fields.Numeric('Sale Price With Tax', digits=(16, 2),
|
|
# depends=['list_price', 'customer_taxes'], required=True)
|
|
|
|
# @fields.depends('customer_taxes', 'sale_price_w_tax', 'customer_taxes_used')
|
|
# def on_change_with_list_price(self):
|
|
# if self.sale_price_w_tax:
|
|
# res = self.compute_reverse_list_price(self.sale_price_w_tax)
|
|
# return res
|
|
|
|
# def compute_reverse_list_price(self, price_w_tax):
|
|
# Tax = Pool().get('account.tax')
|
|
# res = Tax.reverse_compute(price_w_tax, self.customer_taxes_used)
|
|
# res = res.quantize(
|
|
# Decimal(1) / 10 ** self.__class__.list_price.digits[1])
|
|
# print(res, 'res')
|
|
# return res
|
|
|
|
@classmethod
|
|
def default_code_readonly(cls):
|
|
return False
|
|
|
|
def pre_validate(self):
|
|
super().pre_validate()
|
|
pool = Pool()
|
|
Configuration = pool.get('product.configuration')
|
|
required = False
|
|
with Transaction().set_context(self._context):
|
|
config = Configuration(1)
|
|
required = config.get_multivalue('code_required')
|
|
if self.type == 'goods' and self.salable and not self.code and required:
|
|
raise UserError(gettext('sale_pos.msg_missing_code_product'))
|
|
|
|
|
|
class Category(DeactivableMixin, metaclass=PoolMeta):
|
|
__name__ = 'product.category'
|