2014-12-02 12:54:51 +01:00
|
|
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
|
|
|
# this repository contains the full copyright notices and license terms.
|
2011-01-16 22:07:50 +01:00
|
|
|
from decimal import Decimal
|
2012-09-24 22:17:37 +02:00
|
|
|
from trytond.model import fields
|
|
|
|
|
from trytond.pool import Pool, PoolMeta
|
2013-01-13 22:50:22 +01:00
|
|
|
from trytond.transaction import Transaction
|
2013-09-06 22:33:57 +02:00
|
|
|
from trytond import backend
|
2012-09-24 22:17:37 +02:00
|
|
|
|
|
|
|
|
__all__ = ['Move']
|
|
|
|
|
__metaclass__ = PoolMeta
|
2011-01-16 22:07:50 +01:00
|
|
|
|
|
|
|
|
|
2013-08-01 16:07:01 +02:00
|
|
|
def _get_field(type_):
|
|
|
|
|
if type_.startswith('in_'):
|
|
|
|
|
return 'in_anglo_saxon_quantity'
|
|
|
|
|
else:
|
|
|
|
|
return 'out_anglo_saxon_quantity'
|
|
|
|
|
|
|
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
class Move:
|
|
|
|
|
__name__ = 'stock.move'
|
2013-08-01 16:07:01 +02:00
|
|
|
in_anglo_saxon_quantity = fields.Float('Input Anglo-Saxon Quantity',
|
2015-06-17 08:34:58 +02:00
|
|
|
required=True)
|
2013-08-01 16:07:01 +02:00
|
|
|
out_anglo_saxon_quantity = fields.Float('Output Anglo-Saxon Quantity',
|
2015-06-17 08:34:58 +02:00
|
|
|
required=True)
|
2011-01-16 22:07:50 +01:00
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
@classmethod
|
|
|
|
|
def __setup__(cls):
|
|
|
|
|
super(Move, cls).__setup__()
|
2014-02-03 18:01:23 +01:00
|
|
|
cls._allow_modify_closed_period.update(['in_anglo_saxon_quantity',
|
|
|
|
|
'out_anglo_saxon_quantity'])
|
2012-09-24 22:17:37 +02:00
|
|
|
cls._sql_constraints += [
|
2013-08-01 16:07:01 +02:00
|
|
|
('check_in_anglo_saxon_quantity',
|
|
|
|
|
'CHECK(quantity >= in_anglo_saxon_quantity)',
|
|
|
|
|
'Anglo-Saxon quantity can not be greater than quantity.'),
|
|
|
|
|
('check_out_anglo_saxon_quantity',
|
|
|
|
|
'CHECK(quantity >= out_anglo_saxon_quantity)',
|
2013-03-07 16:54:31 +01:00
|
|
|
'Anglo-Saxon quantity can not be greater than quantity.'),
|
2012-09-24 22:17:37 +02:00
|
|
|
]
|
2011-01-16 22:07:50 +01:00
|
|
|
|
2013-08-01 16:07:01 +02:00
|
|
|
@classmethod
|
|
|
|
|
def __register__(cls, module_name):
|
|
|
|
|
cursor = Transaction().cursor
|
2013-09-06 22:33:57 +02:00
|
|
|
TableHandler = backend.get('TableHandler')
|
|
|
|
|
|
2013-08-01 16:07:01 +02:00
|
|
|
super(Move, cls).__register__(module_name)
|
|
|
|
|
table = TableHandler(cursor, cls, module_name)
|
|
|
|
|
|
|
|
|
|
# Migration from 2.8: split anglo_saxon_quantity
|
|
|
|
|
if table.column_exist('anglo_saxon_quantity'):
|
|
|
|
|
cursor.execute('UPDATE "' + cls._table + '" '
|
|
|
|
|
'SET in_anglo_saxon_quantity = anglo_saxon_quantity, '
|
|
|
|
|
'out_anglo_saxon_quantity = anglo_saxon_quantity')
|
|
|
|
|
table.drop_constraint('check_anglo_saxon_quantity')
|
|
|
|
|
table.drop_column('anglo_saxon_quantity')
|
|
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
@staticmethod
|
2013-08-01 16:07:01 +02:00
|
|
|
def default_in_anglo_saxon_quantity():
|
|
|
|
|
return 0.0
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def default_out_anglo_saxon_quantity():
|
2011-01-16 22:07:50 +01:00
|
|
|
return 0.0
|
|
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
def _get_account_stock_move_lines(self, type_):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Uom = pool.get('product.uom')
|
|
|
|
|
AccountMoveLine = pool.get('account.move.line')
|
2013-03-05 10:38:11 +01:00
|
|
|
Currency = pool.get('currency.currency')
|
2012-09-24 22:17:37 +02:00
|
|
|
lines = super(Move, self)._get_account_stock_move_lines(type_)
|
2012-02-06 16:02:26 +01:00
|
|
|
if (type_.endswith('supplier')
|
2012-09-24 22:17:37 +02:00
|
|
|
and self.product.cost_price_method == 'fixed'):
|
|
|
|
|
cost_price = Uom.compute_price(self.product.default_uom,
|
|
|
|
|
self.cost_price, self.uom)
|
2013-03-05 10:38:11 +01:00
|
|
|
with Transaction().set_context(date=self.effective_date):
|
|
|
|
|
unit_price = Currency.compute(self.currency, self.unit_price,
|
|
|
|
|
self.company.currency, round=False)
|
2012-09-24 22:17:37 +02:00
|
|
|
amount = self.company.currency.round(
|
2013-03-05 10:38:11 +01:00
|
|
|
Decimal(str(self.quantity)) * (unit_price - cost_price))
|
2012-09-24 22:17:37 +02:00
|
|
|
if self.company.currency.is_zero(amount):
|
2012-02-06 16:02:26 +01:00
|
|
|
return lines
|
2012-09-24 22:17:37 +02:00
|
|
|
account = self.product.account_stock_supplier_used
|
2012-02-24 10:52:42 +01:00
|
|
|
for move_line in lines:
|
2012-09-24 22:17:37 +02:00
|
|
|
if move_line.account == account:
|
2012-02-24 10:52:42 +01:00
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
return lines
|
2012-02-06 16:02:26 +01:00
|
|
|
if type_.startswith('in_'):
|
2012-09-24 22:17:37 +02:00
|
|
|
move_line.credit += amount
|
2012-02-24 10:52:42 +01:00
|
|
|
debit = amount
|
|
|
|
|
credit = Decimal(0)
|
2012-02-06 16:02:26 +01:00
|
|
|
else:
|
2012-09-24 22:17:37 +02:00
|
|
|
move_line.debit += amount
|
2012-02-24 10:52:42 +01:00
|
|
|
debit = Decimal(0)
|
|
|
|
|
credit = amount
|
|
|
|
|
if amount < Decimal(0):
|
|
|
|
|
debit, credit = -credit, -debit
|
2012-09-24 22:17:37 +02:00
|
|
|
move_line = AccountMoveLine(
|
|
|
|
|
debit=debit,
|
|
|
|
|
credit=credit,
|
|
|
|
|
account=self.product.account_expense_used,
|
|
|
|
|
)
|
2012-02-06 16:02:26 +01:00
|
|
|
lines.append(move_line)
|
|
|
|
|
return lines
|
|
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
@classmethod
|
2013-04-05 00:26:12 +02:00
|
|
|
def _get_anglo_saxon_move(cls, moves, quantity, type_):
|
2011-01-16 22:07:50 +01:00
|
|
|
'''
|
2013-04-05 00:26:12 +02:00
|
|
|
Generator of (move, qty, cost_price) where move is the move to be
|
|
|
|
|
consumed, qty is the quantity (in the product default uom) to be
|
|
|
|
|
consumed on this move and cost_price is in the company currency.
|
2011-01-16 22:07:50 +01:00
|
|
|
'''
|
2013-04-05 00:26:12 +02:00
|
|
|
pool = Pool()
|
|
|
|
|
Uom = pool.get('product.uom')
|
|
|
|
|
Currency = pool.get('currency.currency')
|
2011-01-16 22:07:50 +01:00
|
|
|
|
2013-08-01 16:07:01 +02:00
|
|
|
as_qty_field = _get_field(type_)
|
|
|
|
|
|
2011-01-16 22:07:50 +01:00
|
|
|
consumed_qty = 0.0
|
|
|
|
|
for move in moves:
|
2012-09-24 22:17:37 +02:00
|
|
|
qty = Uom.compute_qty(move.uom,
|
2013-08-01 16:07:01 +02:00
|
|
|
move.quantity - getattr(move, as_qty_field),
|
2011-01-16 22:07:50 +01:00
|
|
|
move.product.default_uom, round=False)
|
|
|
|
|
if qty <= 0.0:
|
|
|
|
|
continue
|
|
|
|
|
if qty > quantity - consumed_qty:
|
|
|
|
|
qty = quantity - consumed_qty
|
|
|
|
|
if consumed_qty >= quantity:
|
|
|
|
|
break
|
2013-04-05 00:26:12 +02:00
|
|
|
|
2015-05-06 18:21:42 +02:00
|
|
|
if type_.endswith('supplier'):
|
2013-04-05 00:26:12 +02:00
|
|
|
with Transaction().set_context(date=move.effective_date):
|
|
|
|
|
unit_price = Currency.compute(move.currency,
|
|
|
|
|
move.unit_price, move.company.currency, round=False)
|
|
|
|
|
cost_price = Uom.compute_price(move.uom,
|
|
|
|
|
unit_price, move.product.default_uom)
|
|
|
|
|
else:
|
|
|
|
|
cost_price = move.cost_price
|
|
|
|
|
|
|
|
|
|
yield (move, qty, cost_price)
|
2014-09-04 22:50:14 +02:00
|
|
|
consumed_qty += qty
|
2011-01-16 22:07:50 +01:00
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
@classmethod
|
|
|
|
|
def update_anglo_saxon_quantity_product_cost(cls, product, moves,
|
2011-01-16 22:07:50 +01:00
|
|
|
quantity, uom, type_):
|
|
|
|
|
'''
|
|
|
|
|
Return the cost for quantity based on lines.
|
|
|
|
|
Update anglo_saxon_quantity on the concerned moves.
|
|
|
|
|
'''
|
2013-03-25 19:30:02 +01:00
|
|
|
pool = Pool()
|
|
|
|
|
Uom = pool.get('product.uom')
|
2011-01-16 22:07:50 +01:00
|
|
|
|
|
|
|
|
for move in moves:
|
|
|
|
|
assert move.product == product, 'wrong product'
|
2012-04-03 20:06:29 +02:00
|
|
|
assert type_.startswith('in_') or type_.startswith('out_'), \
|
|
|
|
|
'wrong type'
|
2011-01-16 22:07:50 +01:00
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
total_qty = Uom.compute_qty(uom, quantity, product.default_uom,
|
2011-01-16 22:07:50 +01:00
|
|
|
round=False)
|
|
|
|
|
|
2013-08-01 16:07:01 +02:00
|
|
|
as_qty_field = _get_field(type_)
|
2011-01-16 22:07:50 +01:00
|
|
|
cost = Decimal('0.0')
|
|
|
|
|
consumed_qty = 0.0
|
2013-04-05 00:26:12 +02:00
|
|
|
for move, move_qty, move_cost_price in cls._get_anglo_saxon_move(
|
|
|
|
|
moves, total_qty, type_):
|
2011-01-16 22:07:50 +01:00
|
|
|
consumed_qty += move_qty
|
|
|
|
|
|
|
|
|
|
cost += move_cost_price * Decimal(str(move_qty))
|
|
|
|
|
|
2015-03-17 10:42:56 +01:00
|
|
|
move_qty = Uom.compute_qty(product.default_uom, move_qty, move.uom)
|
2014-09-17 21:45:07 +02:00
|
|
|
cls.write([move], {
|
|
|
|
|
as_qty_field: (
|
|
|
|
|
(getattr(move, as_qty_field) or 0.0) + move_qty),
|
|
|
|
|
})
|
2011-01-16 22:07:50 +01:00
|
|
|
|
|
|
|
|
if consumed_qty < total_qty:
|
|
|
|
|
qty = total_qty - consumed_qty
|
|
|
|
|
consumed_qty += qty
|
|
|
|
|
cost += product.cost_price * Decimal(str(qty))
|
|
|
|
|
return cost
|
|
|
|
|
|
2012-09-24 22:17:37 +02:00
|
|
|
@classmethod
|
|
|
|
|
def copy(cls, moves, default=None):
|
2012-03-28 17:48:07 +02:00
|
|
|
if default is None:
|
|
|
|
|
default = {}
|
|
|
|
|
default = default.copy()
|
2013-08-01 16:07:01 +02:00
|
|
|
for prefix in ('in_', 'out_'):
|
|
|
|
|
default.setdefault(prefix + 'anglo_saxon_quantity',
|
|
|
|
|
getattr(cls, 'default_%sanglo_saxon_quantity' % prefix)())
|
2012-09-24 22:17:37 +02:00
|
|
|
return super(Move, cls).copy(moves, default=default)
|