341 lines
13 KiB
Python
Executable File
341 lines
13 KiB
Python
Executable File
# 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 ModelView, Workflow
|
|
from trytond.modules.account.exceptions import PeriodNotFoundError
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.transaction import Transaction
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Move(metaclass=PoolMeta):
|
|
__name__ = 'stock.move'
|
|
|
|
def _get_account_stock_move_lines(self, type_, fee=None):
|
|
'''
|
|
Return move lines for stock move
|
|
'''
|
|
pool = Pool()
|
|
Uom = pool.get('product.uom')
|
|
AccountMoveLine = pool.get('account.move.line')
|
|
Currency = pool.get('currency.currency')
|
|
assert type_.startswith('in_') or type_.startswith('out_'), \
|
|
'wrong type'
|
|
|
|
move_line = AccountMoveLine()
|
|
move_line.lot = self.lot
|
|
move_line.fee = fee
|
|
move_line.origin = self
|
|
# cost_price_method = self.product.get_multivalue(
|
|
# 'cost_price_method', **self._cost_price_pattern)
|
|
# if ((
|
|
# type_.endswith('supplier')
|
|
# or type_ in {'in_production', 'in_warehouse'})
|
|
# and cost_price_method != 'fixed'):
|
|
# unit_price = self.unit_price_company
|
|
# else:
|
|
# unit_price = self.cost_price
|
|
# unit_price = self.unit_price
|
|
# unit_price = Uom.compute_price(
|
|
# self.product.default_uom, unit_price, self.unit)
|
|
# amount = self.company.currency.round(
|
|
# Decimal(str(self.quantity)) * unit_price)
|
|
|
|
# if self.to_location.type == 'customer':
|
|
amount = self.lot.get_cog()
|
|
if fee:
|
|
amount = fee.amount
|
|
|
|
if fee and fee.currency != self.company.currency:
|
|
with Transaction().set_context(date=self.effective_date):
|
|
amount_converted = amount
|
|
amount = Currency.compute(fee.currency,
|
|
amount, self.company.currency)
|
|
move_line.second_currency = self.currency
|
|
|
|
if self.currency != self.company.currency and not fee:
|
|
with Transaction().set_context(date=self.effective_date):
|
|
amount_converted = Currency.compute(self.company.currency,
|
|
amount, self.currency)
|
|
move_line.second_currency = self.currency
|
|
|
|
if amount < 0:
|
|
if type_.startswith('in_'):
|
|
move_line.debit = -amount
|
|
move_line.credit = Decimal(0)
|
|
move_line.account = fee.product.account_stock_in_used if fee else self.product.account_stock_in_used
|
|
if hasattr(move_line, 'second_currency') and move_line.second_currency:
|
|
move_line.amount_second_currency = amount_converted
|
|
else:
|
|
move_line.debit = Decimal(0)
|
|
move_line.credit = -amount
|
|
move_line.account = fee.product.account_stock_out_used if fee else self.product.account_stock_out_used
|
|
if hasattr(move_line, 'second_currency') and move_line.second_currency:
|
|
move_line.amount_second_currency = -amount_converted
|
|
else:
|
|
if type_.startswith('in_'):
|
|
move_line.debit = Decimal(0)
|
|
move_line.credit = amount
|
|
move_line.account = fee.product.account_stock_in_used if fee else self.product.account_stock_in_used
|
|
if hasattr(move_line, 'second_currency') and move_line.second_currency:
|
|
move_line.amount_second_currency = -amount_converted
|
|
else:
|
|
move_line.debit = amount
|
|
move_line.credit = Decimal(0)
|
|
move_line.account = fee.product.account_stock_out_used if fee else self.product.account_stock_out_used
|
|
if hasattr(move_line, 'second_currency') and move_line.second_currency:
|
|
move_line.amount_second_currency = amount_converted
|
|
|
|
logger.info("MOVELINES_DEB:%s",move_line.debit)
|
|
logger.info("MOVELINES_CRE:%s",move_line.credit)
|
|
return [move_line]
|
|
|
|
def _get_account_stock_move_line(self, amount, fee=None):
|
|
'''
|
|
Return counterpart move line value for stock move
|
|
'''
|
|
pool = Pool()
|
|
AccountMoveLine = pool.get('account.move.line')
|
|
Currency = pool.get('currency.currency')
|
|
move_line = AccountMoveLine(
|
|
account=fee.product.account_stock_used if fee else self.product.account_stock_used,
|
|
)
|
|
move_line.lot = self.lot
|
|
move_line.fee = fee
|
|
move_line.origin = self
|
|
if not amount:
|
|
return
|
|
|
|
amount_converted = amount
|
|
if (self.currency != self.company.currency and not fee) or (fee and fee.currency != self.company.currency):
|
|
with Transaction().set_context(date=self.effective_date):
|
|
amount_converted = round(Currency.compute(self.company.currency,
|
|
amount, fee.currency if fee else self.currency),2)
|
|
move_line.second_currency = self.currency
|
|
move_line.amount_second_currency = -amount_converted
|
|
|
|
if amount >= Decimal(0):
|
|
move_line.debit = Decimal(0)
|
|
move_line.credit = amount
|
|
else:
|
|
move_line.debit = - amount
|
|
move_line.credit = Decimal(0)
|
|
|
|
if self.to_location.type == 'customer':
|
|
move_line.description = 'Delivery fee' if fee else 'Delivery'
|
|
if self.from_location.type == 'supplier':
|
|
move_line.description = 'Reception fee' if fee else 'Reception'
|
|
|
|
logger.info("MOVELINE_DEB:%s",move_line.debit)
|
|
logger.info("MOVELINE_CRE:%s",move_line.credit)
|
|
return move_line
|
|
|
|
def _get_account_stock_move_type(self):
|
|
'''
|
|
Get account move type
|
|
'''
|
|
type_ = (self.from_location.type, self.to_location.type)
|
|
if type_ in [('supplier', 'storage'), ('supplier', 'drop')]:
|
|
return 'in_supplier'
|
|
elif type_ in [('storage', 'supplier'), ('drop', 'supplier')]:
|
|
return 'out_supplier'
|
|
elif type_ in [('storage', 'customer'), ('drop', 'customer')]:
|
|
return 'out_customer'
|
|
elif type_ in [('customer', 'storage'), ('customer', 'drop')]:
|
|
return 'in_customer'
|
|
elif type_ == ('storage', 'lost_found'):
|
|
return 'out_lost_found'
|
|
elif type_ == ('lost_found', 'storage'):
|
|
return 'in_lost_found'
|
|
elif type_ == ('supplier', 'customer'):
|
|
return 'supplier_customer'
|
|
elif type_ == ('customer', 'supplier'):
|
|
return 'customer_supplier'
|
|
elif type_ == ('storage', 'production'):
|
|
return 'out_production'
|
|
elif type_ == ('production', 'storage'):
|
|
return 'in_production'
|
|
|
|
def _get_account_stock_move(self):
|
|
'''
|
|
Return account move for stock move
|
|
'''
|
|
pool = Pool()
|
|
AccountMove = pool.get('account.move')
|
|
Date = pool.get('ir.date')
|
|
Period = pool.get('account.period')
|
|
AccountConfiguration = pool.get('account.configuration')
|
|
|
|
if self.product.type != 'goods':
|
|
return
|
|
|
|
with Transaction().set_context(company=self.company.id):
|
|
today = Date.today()
|
|
for date in [self.effective_date, today]:
|
|
try:
|
|
period = Period.find(self.company, date=date, test_state=False)
|
|
except PeriodNotFoundError:
|
|
if date < today:
|
|
return
|
|
continue
|
|
break
|
|
else:
|
|
return
|
|
logger.info("PERIOD_STOCK_METHOD:%s",period.fiscalyear.account_stock_method)
|
|
if not period.fiscalyear.account_stock_method:
|
|
return
|
|
if period.state != 'open':
|
|
date = today
|
|
period = Period.find(self.company, date=date)
|
|
|
|
type_ = self._get_account_stock_move_type()
|
|
logger.info("MOVE_TYPE:%s",type_)
|
|
if not type_:
|
|
return
|
|
with Transaction().set_context(
|
|
company=self.company.id, date=date):
|
|
if type_ == 'supplier_customer':
|
|
account_move_lines = self._get_account_stock_move_lines(
|
|
'in_supplier')
|
|
account_move_lines.extend(self._get_account_stock_move_lines(
|
|
'out_customer'))
|
|
elif type_ == 'customer_supplier':
|
|
account_move_lines = self._get_account_stock_move_lines(
|
|
'in_customer')
|
|
account_move_lines.extend(self._get_account_stock_move_lines(
|
|
'out_supplier'))
|
|
else:
|
|
account_move_lines = self._get_account_stock_move_lines(type_)
|
|
|
|
amount = Decimal(0)
|
|
for line in account_move_lines:
|
|
amount += line.debit - line.credit
|
|
# if not amount:
|
|
# return
|
|
move_line = self._get_account_stock_move_line(amount)
|
|
if move_line:
|
|
account_move_lines.append(move_line)
|
|
|
|
account_configuration = AccountConfiguration(1)
|
|
journal = account_configuration.get_multivalue(
|
|
'stock_journal', company=self.company.id)
|
|
logger.info("GET_ACCOUNT_:%s",account_move_lines)
|
|
description = None
|
|
if self.to_location.type == 'customer':
|
|
description = 'Delivery'
|
|
if self.from_location.type == 'supplier':
|
|
description = 'Reception'
|
|
return AccountMove(
|
|
journal=journal,
|
|
period=period,
|
|
date=date,
|
|
origin=self,
|
|
description=description,
|
|
lines=account_move_lines,
|
|
)
|
|
|
|
def _get_account_stock_move_fee(self, fee):
|
|
'''
|
|
Return account move for fee linked to lot of the stock move
|
|
'''
|
|
pool = Pool()
|
|
AccountMove = pool.get('account.move')
|
|
Date = pool.get('ir.date')
|
|
Period = pool.get('account.period')
|
|
AccountConfiguration = pool.get('account.configuration')
|
|
|
|
if fee.product.type != 'service':
|
|
return
|
|
|
|
with Transaction().set_context(company=self.company.id):
|
|
today = Date.today()
|
|
for date in [self.effective_date, today]:
|
|
try:
|
|
period = Period.find(self.company, date=date, test_state=False)
|
|
except PeriodNotFoundError:
|
|
if date < today:
|
|
return
|
|
continue
|
|
break
|
|
else:
|
|
return
|
|
if not period.fiscalyear.account_stock_method:
|
|
return
|
|
if period.state != 'open':
|
|
date = today
|
|
period = Period.find(self.company, date=date)
|
|
|
|
type_ = self._get_account_stock_move_type()
|
|
if not type_:
|
|
return
|
|
with Transaction().set_context(
|
|
company=self.company.id, date=date):
|
|
if type_ == 'supplier_customer':
|
|
account_move_lines = self._get_account_stock_move_lines(
|
|
'in_supplier',fee)
|
|
account_move_lines.extend(self._get_account_stock_move_lines(
|
|
'out_customer',fee))
|
|
elif type_ == 'customer_supplier':
|
|
account_move_lines = self._get_account_stock_move_lines(
|
|
'in_customer',fee)
|
|
account_move_lines.extend(self._get_account_stock_move_lines(
|
|
'out_supplier',fee))
|
|
else:
|
|
account_move_lines = self._get_account_stock_move_lines(type_,fee)
|
|
|
|
amount = Decimal(0)
|
|
for line in account_move_lines:
|
|
amount += line.debit - line.credit
|
|
# if not amount:
|
|
# return
|
|
move_line = self._get_account_stock_move_line(amount,fee)
|
|
if move_line:
|
|
account_move_lines.append(move_line)
|
|
|
|
account_configuration = AccountConfiguration(1)
|
|
journal = account_configuration.get_multivalue(
|
|
'stock_journal', company=self.company.id)
|
|
logger.info("GET_ACCOUNT_FEE:%s",account_move_lines)
|
|
description = None
|
|
if self.to_location.type == 'customer':
|
|
description = 'Delivery fee'
|
|
if self.from_location.type == 'supplier':
|
|
description = 'Reception fee'
|
|
return AccountMove(
|
|
journal=journal,
|
|
period=period,
|
|
date=date,
|
|
origin=self,
|
|
description=description,
|
|
lines=account_move_lines,
|
|
)
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('done')
|
|
def do(cls, moves):
|
|
pool = Pool()
|
|
AccountMove = pool.get('account.move')
|
|
FeeLots = pool.get('fee.lots')
|
|
logger.info("CONTINENTAL_DO_BEFORE:%s",moves)
|
|
super(Move, cls).do(moves)
|
|
logger.info("CONTINENTAL_DO_AFTER:%s",moves)
|
|
account_moves = []
|
|
for move in moves:
|
|
account_move = move._get_account_stock_move()
|
|
if account_move:
|
|
account_moves.append(account_move)
|
|
if move.lot:
|
|
fees = FeeLots.search(['lot','=',move.lot.id])
|
|
for fl in fees:
|
|
if fl.fee.type == 'ordered' and fl.fee.product.template.landed_cost:
|
|
account_move = move._get_account_stock_move_fee(fl.fee)
|
|
if account_move:
|
|
account_moves.append(account_move)
|
|
|
|
AccountMove.save(account_moves)
|
|
#AccountMove.post(account_moves)
|