Maintain negative stock balance if balance qty is negative

This commit is contained in:
Nabin Hait
2014-10-09 19:25:03 +05:30
parent b7e5ad0a31
commit 4d74216147
8 changed files with 118 additions and 50 deletions

View File

@@ -106,18 +106,19 @@ def update_entries_after(args, verbose=1):
stock_queue = [[qty_after_transaction, valuation_rate]]
else:
if valuation_method == "Moving Average":
valuation_rate = get_moving_average_values(qty_after_transaction, sle, valuation_rate)
if flt(sle.actual_qty) > 0:
valuation_rate = get_moving_average_values(qty_after_transaction, sle, valuation_rate)
else:
valuation_rate = get_fifo_values(qty_after_transaction, sle, stock_queue)
qty_after_transaction += flt(sle.actual_qty)
# get stock value
if sle.serial_no:
stock_value = qty_after_transaction * valuation_rate
elif valuation_method == "Moving Average":
stock_value = (qty_after_transaction > 0) and \
(qty_after_transaction * valuation_rate) or 0
stock_value = qty_after_transaction * valuation_rate
else:
stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
@@ -256,64 +257,73 @@ def get_moving_average_values(qty_after_transaction, sle, valuation_rate):
actual_qty = flt(sle.actual_qty)
if not incoming_rate:
# In case of delivery/stock issue in_rate = 0 or wrong incoming rate
# If wrong incoming rate
incoming_rate = valuation_rate
elif qty_after_transaction < 0:
elif qty_after_transaction < 0 and not valuation_rate:
# if negative stock, take current valuation rate as incoming rate
valuation_rate = incoming_rate
new_stock_qty = qty_after_transaction + actual_qty
new_stock_value = qty_after_transaction * valuation_rate + actual_qty * incoming_rate
new_stock_qty = abs(qty_after_transaction) + actual_qty
new_stock_value = (abs(qty_after_transaction) * valuation_rate) + (actual_qty * incoming_rate)
if new_stock_qty > 0 and new_stock_value > 0:
if new_stock_qty:
valuation_rate = new_stock_value / flt(new_stock_qty)
elif new_stock_qty <= 0:
valuation_rate = 0.0
# NOTE: val_rate is same as previous entry if new stock value is negative
return valuation_rate
return abs(valuation_rate)
def get_fifo_values(qty_after_transaction, sle, stock_queue):
incoming_rate = flt(sle.incoming_rate)
actual_qty = flt(sle.actual_qty)
if not stock_queue:
stock_queue.append([0, 0])
intialize_stock_queue(stock_queue, sle.item_code, sle.warehouse)
if actual_qty > 0:
if stock_queue[-1][0] > 0:
stock_queue.append([actual_qty, incoming_rate])
else:
qty = stock_queue[-1][0] + actual_qty
stock_queue[-1] = [qty, qty > 0 and incoming_rate or 0]
if qty == 0:
stock_queue.pop(-1)
else:
stock_queue[-1] = [qty, incoming_rate]
else:
incoming_cost = 0
qty_to_pop = abs(actual_qty)
while qty_to_pop:
if not stock_queue:
stock_queue.append([0, 0])
intialize_stock_queue(stock_queue, sle.item_code, sle.warehouse)
batch = stock_queue[0]
if 0 < batch[0] <= qty_to_pop:
# if batch qty > 0
# not enough or exactly same qty in current batch, clear batch
incoming_cost += flt(batch[0]) * flt(batch[1])
qty_to_pop -= batch[0]
# print qty_to_pop, batch
if qty_to_pop >= batch[0]:
# consume current batch
qty_to_pop = qty_to_pop - batch[0]
stock_queue.pop(0)
if not stock_queue and qty_to_pop:
# stock finished, qty still remains to be withdrawn
# negative stock, keep in as a negative batch
stock_queue.append([-qty_to_pop, batch[1]])
break
else:
# all from current batch
incoming_cost += flt(qty_to_pop) * flt(batch[1])
batch[0] -= qty_to_pop
# qty found in current batch
# consume it and exit
batch[0] = batch[0] - qty_to_pop
qty_to_pop = 0
stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
stock_qty = sum((flt(batch[0]) for batch in stock_queue))
valuation_rate = stock_qty and (stock_value / flt(stock_qty)) or 0
valuation_rate = (stock_value / flt(stock_qty)) if stock_qty else 0
return valuation_rate
return abs(valuation_rate)
def intialize_stock_queue(stock_queue, item_code, warehouse):
if not stock_queue:
from erpnext.controllers.stock_controller import get_valuation_rate
estimated_val_rate = get_valuation_rate(item_code, warehouse)
stock_queue.append([0, estimated_val_rate])
def _raise_exceptions(args, verbose=1):
deficiency = min(e["diff"] for e in _exceptions)