Skip to content

Commit

Permalink
fix: negative stock balance (frappe#44990)
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitwaghchaure authored Dec 31, 2024
1 parent d6980a9 commit 7c4aecf
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
58 changes: 54 additions & 4 deletions erpnext/stock/deprecated_serial_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ def calculate_avg_rate_for_non_batchwise_valuation(self):
stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty
self.stock_value_change += stock_value_change

self.non_batchwise_balance_value[batch_no] -= stock_value_change
self.non_batchwise_balance_qty[batch_no] -= ledger.qty

frappe.db.set_value(
"Serial and Batch Entry",
ledger.name,
Expand Down Expand Up @@ -254,7 +257,6 @@ def set_balance_value_from_sl_entries(self) -> None:
.select(
sle.batch_no,
Sum(sle.actual_qty).as_("batch_qty"),
Sum(sle.stock_value_difference).as_("batch_value"),
)
.where(
(sle.item_code == self.sle.item_code)
Expand All @@ -271,11 +273,59 @@ def set_balance_value_from_sl_entries(self) -> None:
if self.sle.name:
query = query.where(sle.name != self.sle.name)

for d in query.run(as_dict=True):
self.non_batchwise_balance_value[d.batch_no] += flt(d.batch_value)
self.non_batchwise_balance_qty[d.batch_no] += flt(d.batch_qty)
batch_data = query.run(as_dict=True)
for d in batch_data:
self.available_qty[d.batch_no] += flt(d.batch_qty)

last_sle = self.get_last_sle_for_non_batch()
for d in batch_data:
self.non_batchwise_balance_value[d.batch_no] += flt(last_sle.stock_value)
self.non_batchwise_balance_qty[d.batch_no] += flt(last_sle.qty_after_transaction)

def get_last_sle_for_non_batch(self):
from erpnext.stock.utils import get_combine_datetime

sle = frappe.qb.DocType("Stock Ledger Entry")
batch = frappe.qb.DocType("Batch")

posting_datetime = get_combine_datetime(self.sle.posting_date, self.sle.posting_time)
if not self.sle.creation:
posting_datetime = posting_datetime + datetime.timedelta(milliseconds=1)

timestamp_condition = sle.posting_datetime < posting_datetime

if self.sle.creation:
timestamp_condition |= (sle.posting_datetime == posting_datetime) & (
sle.creation < self.sle.creation
)

query = (
frappe.qb.from_(sle)
.inner_join(batch)
.on(sle.batch_no == batch.name)
.select(
sle.stock_value,
sle.qty_after_transaction,
)
.where(
(sle.item_code == self.sle.item_code)
& (sle.warehouse == self.sle.warehouse)
& (sle.batch_no.isnotnull())
& (batch.use_batchwise_valuation == 0)
& (sle.is_cancelled == 0)
)
.where(timestamp_condition)
.orderby(sle.posting_datetime, order=Order.desc)
.orderby(sle.creation, order=Order.desc)
.limit(1)
)

if self.sle.name:
query = query.where(sle.name != self.sle.name)

data = query.run(as_dict=True)
return data[0] if data else {}

@deprecated(
"erpnext.stock.serial_batch_bundle.BatchNoValuation.set_balance_value_from_bundle",
"unknown",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def test_old_batch_valuation(self):
for qty, valuation in {10: 100, 20: 200}.items():
stock_queue.append([qty, valuation])
qty_after_transaction += qty
balance_value += qty_after_transaction * valuation
balance_value += qty * valuation

doc = frappe.get_doc(
{
Expand All @@ -186,6 +186,7 @@ def test_old_batch_valuation(self):
"incoming_rate": valuation,
"qty_after_transaction": qty_after_transaction,
"stock_value_difference": valuation * qty,
"stock_value": balance_value,
"balance_value": balance_value,
"valuation_rate": balance_value / qty_after_transaction,
"actual_qty": qty,
Expand Down

0 comments on commit 7c4aecf

Please sign in to comment.