# 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 decimal import Decimal from trytond.model import fields from trytond.modules.account_product.product import ( account_used, template_property) from trytond.pool import Pool, PoolMeta from trytond.pyson import Eval from trytond.transaction import Transaction account_names = [ 'account_stock', 'account_stock_in', 'account_stock_out'] class Category(metaclass=PoolMeta): __name__ = 'product.category' account_stock = fields.MultiValue(fields.Many2One( 'account.account', "Account Stock", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('type.statement', '=', 'balance'), ('company', '=', Eval('context', {}).get('company', -1)), ], states={ 'invisible': (~Eval('context', {}).get('company') | Eval('account_parent') | ~Eval('accounting', False)), })) account_stock_in = fields.MultiValue(fields.Many2One( 'account.account', "Account Stock IN", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('company', '=', Eval('context', {}).get('company', -1)), ], states={ 'invisible': (~Eval('context', {}).get('company') | Eval('account_parent') | ~Eval('accounting', False)), })) account_stock_out = fields.MultiValue(fields.Many2One( 'account.account', "Account Stock OUT", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('company', '=', Eval('context', {}).get('company', -1)), ], states={ 'invisible': (~Eval('context', {}).get('company') | Eval('account_parent') | ~Eval('accounting', False)), })) @classmethod def __setup__(cls): pool = Pool() CategoryAccount = pool.get('product.category.account') super().__setup__() for account in [cls.account_stock_in, cls.account_stock_out]: account.domain = [ account.domain, ('type.statement', 'in', CategoryAccount.get_account_stock_type_statements()), ] @classmethod def multivalue_model(cls, field): pool = Pool() if field in account_names: return pool.get('product.category.account') return super().multivalue_model(field) @property @account_used('account_stock') def account_stock_used(self): pass @property @account_used('account_stock_in') def account_stock_in_used(self): pass @property @account_used('account_stock_out') def account_stock_out_used(self): pass @fields.depends( 'accounting', 'account_stock', 'account_stock_in', 'account_stock_out') def on_change_accounting(self): super().on_change_accounting() if not self.accounting: self.account_stock = None self.account_stock_in = None self.account_stock_out = None class CategoryAccount(metaclass=PoolMeta): __name__ = 'product.category.account' account_stock = fields.Many2One( 'account.account', "Account Stock", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('type.statement', '=', 'balance'), ('company', '=', Eval('company', -1)), ]) account_stock_in = fields.Many2One( 'account.account', "Account Stock IN", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('company', '=', Eval('company', -1)), ]) account_stock_out = fields.Many2One( 'account.account', "Account Stock OUT", domain=[ ('closed', '!=', True), ('type.stock', '=', True), ('company', '=', Eval('company', -1)), ]) @classmethod def __setup__(cls): super().__setup__() for account in [cls.account_stock_in, cls.account_stock_out]: account.domain = [ account.domain, ('type.statement', 'in', cls.get_account_stock_type_statements()), ] @classmethod def get_account_stock_type_statements(cls): return ['income'] class Template(metaclass=PoolMeta): __name__ = 'product.template' @classmethod def __setup__(cls): super().__setup__() cls._modify_no_move.append( ('cost_price', 'account_stock_continental.msg_product_change_cost_price')) @property @account_used('account_stock', 'account_category') def account_stock_used(self): pass @property @account_used('account_stock_in', 'account_category') def account_stock_in_used(self): pass @property @account_used('account_stock_out', 'account_category') def account_stock_out_used(self): pass class Product(metaclass=PoolMeta): __name__ = 'product.product' account_stock_used = template_property('account_stock_used') account_stock_in_used = template_property('account_stock_in_used') account_stock_out_used = template_property('account_stock_out_used') @classmethod def update_cost_price(cls, costs): pool = Pool() Date = pool.get('ir.date') Stock = pool.get('stock.location') Company = pool.get('company.company') Move = pool.get('account.move') Period = pool.get('account.period') context = Transaction().context locations = Stock.search([('type', '=', 'storage')]) company = Company(context['company']) with Transaction().set_context(company=company.id): stock_date_end = Date.today() period = Period.find(company, date=stock_date_end) if period.fiscalyear.account_stock_method: moves = [] with Transaction().set_context(locations=[l.id for l in locations], stock_date_end=stock_date_end): for cost, products in costs.items(): products = cls.browse(products) for product in products: difference = cost - product.cost_price quantity = product.quantity amount = company.currency.round( Decimal(str(quantity)) * difference) if amount: moves.append(product._update_cost_price_move( amount, company, period, stock_date_end)) Move.save(moves) Move.post(moves) super().update_cost_price(costs) def _update_cost_price_move(self, amount, company, period, date): pool = Pool() AccountConfiguration = pool.get('account.configuration') Move = pool.get('account.move') Line = pool.get('account.move.line') config = AccountConfiguration(1) if amount > 0: account = self.account_stock_in_used else: account = self.account_stock_out_used return Move( period=period, journal=config.stock_journal, date=date, origin=self, lines=[Line( debit=amount if amount > 0 else 0, credit=-amount if amount < 0 else 0, account=self.account_stock_used, ), Line( debit=-amount if amount < 0 else 0, credit=amount if amount > 0 else 0, account=account, ), ], )