fix(report): cost-based opening balance in agricultural stock report

Opening balance now subtracts sales before the period at their COGS
(via the company's FIFO/Moving Average method) instead of at sale price.
This keeps it consistent with the cost-based closing balance, so each
period's opening equals the previous period's closing and the value can
no longer go negative while stock remains.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali 2026-06-24 17:27:26 +00:00
parent 18e55b7421
commit f906536b7f
1 changed files with 17 additions and 11 deletions

View File

@ -237,24 +237,30 @@ def get_data(filters=None):
purchases = _fetch_rows("Purchase Invoice", "Purchase Invoice Item", company, to_date) purchases = _fetch_rows("Purchase Invoice", "Purchase Invoice Item", company, to_date)
sales = _fetch_rows("Sales Invoice", "Sales Invoice Item", company, to_date) sales = _fetch_rows("Sales Invoice", "Sales Invoice Item", company, to_date)
# Opening balance = cumulative (purchases - sales) before the period start. # Pick the cost-of-goods-sold method from the company's Default Stock
# Valuation Method. Moving Average -> weighted average, otherwise FIFO.
valuation_method = _get_valuation_method(company)
def cogs(start, end):
if valuation_method == "Moving Average":
return _avg_sold_purchase_price(purchases, sales, start, end)
return _fifo_sold_purchase_price(purchases, sales, start, end)
# Opening balance = cost (purchase price) of stock still on hand at the
# start of the period = all purchases before the period minus the COST of
# all goods sold before it. Subtracting sales at COGS (not sale price)
# keeps it consistent with the closing balance, so each period's opening
# equals the previous period's closing.
if from_date: if from_date:
opening_purchases = _sum_gross(purchases, end=_day_before(from_date)) opening_purchases = _sum_gross(purchases, end=_day_before(from_date))
opening_sales = _sum_gross(sales, end=_day_before(from_date)) opening_cogs = cogs(None, _day_before(from_date))
opening_balance = opening_purchases - opening_sales opening_balance = opening_purchases - opening_cogs
else: else:
opening_balance = 0.0 opening_balance = 0.0
purchased = _sum_gross(purchases, start=from_date, end=to_date) purchased = _sum_gross(purchases, start=from_date, end=to_date)
sold = _sum_gross(sales, start=from_date, end=to_date) sold = _sum_gross(sales, start=from_date, end=to_date)
sold_purchase_price = cogs(from_date, to_date)
# Pick the cost-of-goods-sold method from the company's Default Stock
# Valuation Method. Moving Average -> weighted average, otherwise FIFO.
valuation_method = _get_valuation_method(company)
if valuation_method == "Moving Average":
sold_purchase_price = _avg_sold_purchase_price(purchases, sales, from_date, to_date)
else:
sold_purchase_price = _fifo_sold_purchase_price(purchases, sales, from_date, to_date)
# Closing balance at purchase price = opening + purchased - cost of goods # Closing balance at purchase price = opening + purchased - cost of goods
# sold (COGS, valued per the company's stock valuation method). # sold (COGS, valued per the company's stock valuation method).