Update for new Transaction
This commit is contained in:
1 parent
11c2a87ccb
commit
397f836684
3 files changed
+67
-91
No files matched your search
@@ -4,7 +4,7 @@ Installing trytond_product_cost_fifo
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Python 2.4 or later (http://www.python.org/)
|
||||
* Python 2.5 or later (http://www.python.org/)
|
||||
* trytond (http://www.tryton.org/)
|
||||
* trytond_product (http://www.tryton.org/)
|
||||
* trytond_stock (http://www.tryton.org/)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#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, ModelSQL, fields
|
||||
from trytond.pyson import Eval
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class Move(ModelSQL, ModelView):
|
||||
@@ -22,22 +22,18 @@ class Move(ModelSQL, ModelView):
|
||||
'for FIFO cost price!',
|
||||
})
|
||||
|
||||
def default_fifo_quantity_out(self, cursor, user, context=None):
|
||||
def default_fifo_quantity_out(self):
|
||||
return 0.0
|
||||
|
||||
def _update_fifo_out_product_cost_price(self, cursor, user, product,
|
||||
quantity, uom, context=None):
|
||||
def _update_fifo_out_product_cost_price(self, product, quantity, uom):
|
||||
'''
|
||||
Update the product cost price of the given product. Update
|
||||
fifo_quantity on the concerned incomming moves. Return the
|
||||
cost price for outputing the given product and quantity.
|
||||
|
||||
:param cursor: the database cursor
|
||||
:param user: the user id
|
||||
:param product: a BrowseRecord of the product
|
||||
:param quantity: the quantity of the outgoing product
|
||||
:param uom: the uom id or a BrowseRecord of the uom
|
||||
:param context: the context
|
||||
:return: cost_price (of type decimal)
|
||||
'''
|
||||
|
||||
@@ -45,14 +41,12 @@ class Move(ModelSQL, ModelView):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
|
||||
if isinstance(uom, (int, long)):
|
||||
uom = uom_obj.browse(cursor, user, uom, context=context)
|
||||
uom = uom_obj.browse(uom)
|
||||
|
||||
total_qty = uom_obj.compute_qty(
|
||||
cursor, user, uom, quantity, product.default_uom, round=False,
|
||||
context=context)
|
||||
total_qty = uom_obj.compute_qty(uom, quantity, product.default_uom,
|
||||
round=False)
|
||||
|
||||
fifo_moves = template_obj.get_fifo_move(
|
||||
cursor, user, product.template.id, total_qty, context=context)
|
||||
fifo_moves = template_obj.get_fifo_move(product.template.id, total_qty)
|
||||
|
||||
|
||||
cost_price = Decimal("0.0")
|
||||
@@ -60,22 +54,19 @@ class Move(ModelSQL, ModelView):
|
||||
for move, move_qty in fifo_moves:
|
||||
consumed_qty += move_qty
|
||||
|
||||
move_unit_price = uom_obj.compute_price(
|
||||
cursor, user, move.uom, move.unit_price,
|
||||
move.product.default_uom, context=context)
|
||||
move_unit_price = uom_obj.compute_price(move.uom, move.unit_price,
|
||||
move.product.default_uom)
|
||||
cost_price += move_unit_price * Decimal(str(move_qty))
|
||||
|
||||
self._update_product_cost_price(
|
||||
cursor, user, product.id, -move_qty, product.default_uom,
|
||||
move_unit_price, move.currency, move.company, context=context)
|
||||
self._update_product_cost_price(product.id, -move_qty,
|
||||
product.default_uom, move_unit_price, move.currency,
|
||||
move.company)
|
||||
|
||||
move_qty = uom_obj.compute_qty(
|
||||
cursor, user, product.default_uom, move_qty, move.uom,
|
||||
round=False, context=context)
|
||||
self.write(
|
||||
cursor, user, move.id,
|
||||
{'fifo_quantity': (move.fifo_quantity or 0.0) + move_qty},
|
||||
context=context)
|
||||
move_qty = uom_obj.compute_qty(product.default_uom, move_qty,
|
||||
move.uom, round=False)
|
||||
self.write(move.id, {
|
||||
'fifo_quantity': (move.fifo_quantity or 0.0) + move_qty,
|
||||
})
|
||||
|
||||
|
||||
if Decimal(str(consumed_qty)) != Decimal("0"):
|
||||
@@ -88,93 +79,82 @@ class Move(ModelSQL, ModelView):
|
||||
else:
|
||||
return product.cost_price
|
||||
|
||||
def create(self, cursor, user, vals, context=None):
|
||||
def create(self, vals):
|
||||
location_obj = self.pool.get('stock.location')
|
||||
product_obj = self.pool.get('product.product')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
|
||||
if vals.get('state') == 'done':
|
||||
from_location = location_obj.browse(cursor, user,
|
||||
vals['from_location'], context=context)
|
||||
to_location = location_obj.browse(cursor, user,
|
||||
vals['to_location'], context=context)
|
||||
product = product_obj.browse(cursor, user, vals['product'],
|
||||
context=context)
|
||||
from_location = location_obj.browse(vals['from_location'])
|
||||
to_location = location_obj.browse(vals['to_location'])
|
||||
product = product_obj.browse(vals['product'])
|
||||
if from_location.type == 'supplier' \
|
||||
and product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
vals['product'], vals['quantity'], vals['uom'],
|
||||
vals['unit_price'], vals['currency'],
|
||||
context=context)
|
||||
self._update_product_cost_price(vals['product'],
|
||||
vals['quantity'], vals['uom'], vals['unit_price'],
|
||||
vals['currency'])
|
||||
if to_location.type == 'supplier' \
|
||||
and product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
vals['product'], -vals['quantity'], vals['uom'],
|
||||
vals['unit_price'], vals['currency'],
|
||||
context=context)
|
||||
self._update_product_cost_price(vals['product'],
|
||||
-vals['quantity'], vals['uom'], vals['unit_price'],
|
||||
vals['currency'])
|
||||
if to_location.type != 'storage' \
|
||||
and to_location.type != 'supplier' \
|
||||
and product.cost_price_method == 'fifo':
|
||||
|
||||
cost_price = self._update_fifo_out_product_cost_price(
|
||||
cursor, user, product, vals['quantity'], vals['uom'],
|
||||
context=context)
|
||||
cost_price = self._update_fifo_out_product_cost_price(product,
|
||||
vals['quantity'], vals['uom'])
|
||||
if not vals.get('cost_price'):
|
||||
vals['cost_price'] = cost_price
|
||||
|
||||
return super(Move, self).create(cursor, user, vals, context=context)
|
||||
return super(Move, self).create(vals)
|
||||
|
||||
def write(self, cursor, user, ids, vals, context=None):
|
||||
def write(self, ids, vals):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
if 'state' in vals and vals['state'] == 'done':
|
||||
for move in self.browse(cursor, user, ids, context=context):
|
||||
for move in self.browse(ids):
|
||||
if vals['state'] == 'cancel':
|
||||
if move.from_location.type == 'supplier' \
|
||||
and move.state != 'cancel' \
|
||||
and move.product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
move.product.id, -move.quantity, move.uom,
|
||||
move.unit_price, move.currency, move.company,
|
||||
context=context)
|
||||
self._update_product_cost_price(move.product.id,
|
||||
-move.quantity, move.uom, move.unit_price,
|
||||
move.currency, move.company)
|
||||
if move.to_location.type == 'supplier' \
|
||||
and move.state != 'cancel' \
|
||||
and move.product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
move.product.id, move.quantity, move.uom,
|
||||
move.unit_price, move.currency, move.company,
|
||||
context=context)
|
||||
self._update_product_cost_price(move.product.id,
|
||||
move.quantity, move.uom, move.unit_price,
|
||||
move.currency, move.company)
|
||||
|
||||
elif vals['state'] == 'done':
|
||||
if move.from_location.type == 'supplier' \
|
||||
and move.state != 'done' \
|
||||
and move.product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
move.product.id, move.quantity, move.uom,
|
||||
move.unit_price, move.currency, move.company,
|
||||
context=context)
|
||||
self._update_product_cost_price(move.product.id,
|
||||
move.quantity, move.uom, move.unit_price,
|
||||
move.currency, move.company)
|
||||
if move.to_location.type == 'supplier' \
|
||||
and move.state != 'done' \
|
||||
and move.product.cost_price_method == 'fifo':
|
||||
self._update_product_cost_price(cursor, user,
|
||||
move.product.id, -move.quantity, move.uom,
|
||||
move.unit_price, move.currency, move.company,
|
||||
context=context)
|
||||
self._update_product_cost_price(move.product.id,
|
||||
-move.quantity, move.uom, move.unit_price,
|
||||
move.currency, move.company)
|
||||
if move.to_location.type != 'storage' \
|
||||
and move.to_location.type != 'supplier' \
|
||||
and move.product.cost_price_method == 'fifo':
|
||||
cost_price = self._update_fifo_out_product_cost_price(
|
||||
cursor, user, move.product, move.quantity,
|
||||
move.uom, context=context)
|
||||
move.product, move.quantity, move.uom)
|
||||
if not vals.get('cost_price'):
|
||||
vals['cost_price'] = cost_price
|
||||
return super(Move, self).write(cursor, user, ids, vals, context=context)
|
||||
return super(Move, self).write(ids, vals)
|
||||
|
||||
def delete(self, cursor, user, ids, context=None):
|
||||
if self.search(cursor, user, [
|
||||
def delete(self, ids):
|
||||
if self.search([
|
||||
('id', 'in', ids),
|
||||
('fifo_quantity', '!=', 0.0),
|
||||
], context=context):
|
||||
self.raise_user_error(cursor, 'del_move_fifo', context=context)
|
||||
return super(Move, self).delete(cursor, user, ids, context=context)
|
||||
]):
|
||||
self.raise_user_error('del_move_fifo')
|
||||
return super(Move, self).delete(ids)
|
||||
Move()
|
||||
+15
-19
@@ -1,8 +1,9 @@
|
||||
#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 ModelView, ModelSQL, fields
|
||||
from __future__ import with_statement
|
||||
import copy
|
||||
import datetime
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
|
||||
|
||||
class Template(ModelSQL, ModelView):
|
||||
@@ -16,19 +17,15 @@ class Template(ModelSQL, ModelView):
|
||||
self.cost_price_method.selection.append(new_sel)
|
||||
self._reset_columns()
|
||||
|
||||
def get_fifo_move(self, cursor, user, template_id, quantity=0.0,
|
||||
context=None):
|
||||
def get_fifo_move(self, template_id, quantity=0.0):
|
||||
'''
|
||||
Return a list of (move, qty) where move is the move to be
|
||||
consumed and qty is the quantity (in the product default uom)
|
||||
to be consumed on this move. The list contains the "first in"
|
||||
moves for the given quantity.
|
||||
|
||||
:param cursor: the database cursor
|
||||
:param user: the user id
|
||||
:param template_id: the product template id
|
||||
:param quantity: the quantity to be removed from the stock
|
||||
:param context: the context
|
||||
:return: list of (move, qty) where move is a browse record,
|
||||
qty is a float
|
||||
'''
|
||||
@@ -36,35 +33,34 @@ class Template(ModelSQL, ModelView):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
location_obj = self.pool.get('stock.location')
|
||||
|
||||
ctx = context and context.copy() or {}
|
||||
ctx['locations'] = location_obj.search(cursor, user, [
|
||||
locations = location_obj.search([
|
||||
('type', '=', 'storage'),
|
||||
], context=context)
|
||||
ctx['stock_date_end'] = datetime.date.today()
|
||||
])
|
||||
stock_date_end = datetime.date.today()
|
||||
|
||||
template = self.browse(cursor, user, template_id, context=ctx)
|
||||
with Transaction().set_context(locations=locations,
|
||||
stock_date_end=stock_date_end):
|
||||
template = self.browse(template_id)
|
||||
offset = 0
|
||||
limit = cursor.IN_MAX
|
||||
limit = Transaction().cursor.IN_MAX
|
||||
avail_qty = template.quantity
|
||||
fifo_moves = []
|
||||
|
||||
while avail_qty > 0.0:
|
||||
move_ids = move_obj.search(cursor, user, [
|
||||
move_ids = move_obj.search([
|
||||
('product.template.id', '=', template.id),
|
||||
('state', '=', 'done'),
|
||||
('from_location.type', '=', 'supplier'),
|
||||
], offset=offset, limit=limit,
|
||||
order=[('effective_date', 'DESC'), ('id', 'DESC')],
|
||||
context=context)
|
||||
order=[('effective_date', 'DESC'), ('id', 'DESC')])
|
||||
if not move_ids:
|
||||
break
|
||||
offset += limit
|
||||
|
||||
for move in move_obj.browse(cursor, user, move_ids,
|
||||
context=context):
|
||||
qty = uom_obj.compute_qty(cursor, user, move.uom,
|
||||
for move in move_obj.browse(move_ids):
|
||||
qty = uom_obj.compute_qty(move.uom,
|
||||
move.quantity - move.fifo_quantity,
|
||||
template.default_uom, round=False, context=context)
|
||||
template.default_uom, round=False)
|
||||
avail_qty -= qty
|
||||
|
||||
if avail_qty <= quantity:
|
||||
|
||||
Reference in new issue
Block a user