Skip to content

Commit 60f8654

Browse files
Merge pull request #50506 from mihir-kandoi/company-wise-valuation-method
feat: company wise valuation method
2 parents b2a0cdf + 316b6d6 commit 60f8654

File tree

12 files changed

+74
-22
lines changed

12 files changed

+74
-22
lines changed

erpnext/controllers/sales_and_purchase_return.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
import erpnext
1414
from erpnext.stock.serial_batch_bundle import get_batches_from_bundle
15-
from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle
1615
from erpnext.stock.utils import get_combine_datetime, get_incoming_rate, get_valuation_method
1716

1817

@@ -145,7 +144,7 @@ def validate_returned_items(doc):
145144
ref.rate
146145
and flt(d.rate) > ref.rate
147146
and doc.doctype in ("Delivery Note", "Sales Invoice")
148-
and get_valuation_method(ref.item_code) != "Moving Average"
147+
and get_valuation_method(ref.item_code, doc.company) != "Moving Average"
149148
):
150149
frappe.throw(
151150
_("Row # {0}: Rate cannot be greater than the rate used in {1} {2}").format(

erpnext/controllers/selling_controller.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ def set_incoming_rate(self):
524524
)
525525

526526
if not self.get("return_against") or (
527-
get_valuation_method(d.item_code) == "Moving Average"
527+
get_valuation_method(d.item_code, self.company) == "Moving Average"
528528
and self.get("is_return")
529529
and not item_details.has_serial_no
530530
and not item_details.has_batch_no
@@ -535,7 +535,10 @@ def set_incoming_rate(self):
535535
if (
536536
not d.incoming_rate
537537
or self.is_internal_transfer()
538-
or (get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return"))
538+
or (
539+
get_valuation_method(d.item_code, self.company) == "Moving Average"
540+
and self.get("is_return")
541+
)
539542
):
540543
d.incoming_rate = get_incoming_rate(
541544
{
@@ -560,7 +563,7 @@ def set_incoming_rate(self):
560563
not d.incoming_rate
561564
and self.get("return_against")
562565
and self.get("is_return")
563-
and get_valuation_method(d.item_code) == "Moving Average"
566+
and get_valuation_method(d.item_code, self.company) == "Moving Average"
564567
):
565568
d.incoming_rate = get_rate_for_return(
566569
self.doctype, self.name, d.item_code, self.return_against, item_row=d

erpnext/patches.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,5 @@ erpnext.patches.v16_0.add_new_stock_entry_types
446446
erpnext.patches.v15_0.set_asset_status_if_not_already_set
447447
erpnext.patches.v15_0.toggle_legacy_controller_for_period_closing
448448
erpnext.patches.v16_0.update_serial_batch_entries
449-
erpnext.patches.v16_0.set_company_wise_warehouses
449+
erpnext.patches.v16_0.set_company_wise_warehouses
450+
erpnext.patches.v16_0.set_valuation_method_on_companies
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import frappe
2+
3+
4+
def execute():
5+
valuation_method = frappe.get_single_value("Stock Settings", "valuation_method")
6+
for company in frappe.get_all("Company", pluck="name"):
7+
frappe.db.set_value("Company", company, "valuation_method", valuation_method)

erpnext/setup/doctype/company/company.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"enable_item_wise_inventory_account",
118118
"enable_provisional_accounting_for_non_stock_items",
119119
"default_inventory_account",
120+
"valuation_method",
120121
"column_break_32",
121122
"stock_adjustment_account",
122123
"stock_received_but_not_billed",
@@ -890,6 +891,14 @@
890891
"fieldtype": "Check",
891892
"label": "Enable Item-wise Inventory Account"
892893
},
894+
{
895+
"default": "FIFO",
896+
"fieldname": "valuation_method",
897+
"fieldtype": "Select",
898+
"label": "Default Stock Valuation Method",
899+
"options": "FIFO\nMoving Average\nLIFO",
900+
"reqd": 1
901+
},
893902
{
894903
"fieldname": "default_wip_warehouse",
895904
"fieldtype": "Link",

erpnext/setup/doctype/company/company.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class Company(NestedSet):
116116
transactions_annual_history: DF.Code | None
117117
unrealized_exchange_gain_loss_account: DF.Link | None
118118
unrealized_profit_loss_account: DF.Link | None
119+
valuation_method: DF.Literal["FIFO", "Moving Average", "LIFO"]
119120
website: DF.Data | None
120121
write_off_account: DF.Link | None
121122
# end: auto-generated types
@@ -166,6 +167,32 @@ def validate(self):
166167
self.validate_parent_company()
167168
self.set_reporting_currency()
168169
self.validate_inventory_account_settings()
170+
self.cant_change_valuation_method()
171+
172+
def cant_change_valuation_method(self):
173+
doc_before_save = self.get_doc_before_save()
174+
if not doc_before_save:
175+
return
176+
177+
previous_valuation_method = doc_before_save.get("valuation_method")
178+
179+
if previous_valuation_method and previous_valuation_method != self.valuation_method:
180+
# check if there are any stock ledger entries against items
181+
# which does not have it's own valuation method
182+
sle = frappe.db.sql(
183+
"""select name from `tabStock Ledger Entry` sle
184+
where exists(select name from tabItem
185+
where name=sle.item_code and (valuation_method is null or valuation_method='')) and sle.company=%s limit 1
186+
""",
187+
self.name,
188+
)
189+
190+
if sle:
191+
frappe.throw(
192+
_(
193+
"Can't change the valuation method, as there are transactions against some items which do not have its own valuation method"
194+
)
195+
)
169196

170197
def validate_inventory_account_settings(self):
171198
doc_before_save = self.get_doc_before_save()

erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ def set_incoming_rate_for_outward_transaction(self, row=None, save=False, allow_
514514
if hasattr(sn_obj, "stock_queue") and sn_obj.stock_queue:
515515
stock_queue = parse_json(sn_obj.stock_queue)
516516

517-
val_method = get_valuation_method(self.item_code)
517+
val_method = get_valuation_method(self.item_code, self.company)
518518

519519
for d in self.entries:
520520
available_qty = 0
@@ -642,7 +642,7 @@ def get_return_against(self, parent=None):
642642
def set_incoming_rate_for_inward_transaction(self, row=None, save=False, prev_sle=None):
643643
from erpnext.stock.utils import get_valuation_method
644644

645-
valuation_method = get_valuation_method(self.item_code)
645+
valuation_method = get_valuation_method(self.item_code, self.company)
646646

647647
valuation_field = "valuation_rate"
648648
if self.voucher_type in ["Sales Invoice", "Delivery Note", "Quotation"]:

erpnext/stock/report/stock_ageing/stock_ageing.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def format_report_data(filters: Filters, item_details: dict, to_date: str) -> li
5252
range_values = get_range_age(filters, fifo_queue, to_date, item_dict)
5353

5454
check_and_replace_valuations_if_moving_average(
55-
range_values, details.valuation_method, details.valuation_rate
55+
range_values, details.valuation_method, details.valuation_rate, filters.get("company")
5656
)
5757

5858
row = [details.name, details.item_name, details.description, details.item_group, details.brand]
@@ -76,10 +76,12 @@ def format_report_data(filters: Filters, item_details: dict, to_date: str) -> li
7676
return data
7777

7878

79-
def check_and_replace_valuations_if_moving_average(range_values, item_valuation_method, valuation_rate):
79+
def check_and_replace_valuations_if_moving_average(
80+
range_values, item_valuation_method, valuation_rate, company
81+
):
8082
if item_valuation_method == "Moving Average" or (
8183
not item_valuation_method
82-
and frappe.db.get_single_value("Stock Settings", "valuation_method") == "Moving Average"
84+
and frappe.get_cached_value("Company", company, "valuation_method") == "Moving Average"
8385
):
8486
for i in range(0, len(range_values), 2):
8587
range_values[i + 1] = range_values[i] * valuation_rate

erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def get_columns():
201201
def get_data(filters=None):
202202
filters = frappe._dict(filters or {})
203203
item_warehouse_map = get_item_warehouse_combinations(filters)
204-
valuation_method = frappe.db.get_single_value("Stock Settings", "valuation_method")
204+
valuation_method = frappe.get_cached_value("Company", filters.get("company"), "valuation_method")
205205

206206
data = []
207207
if item_warehouse_map:

erpnext/stock/serial_batch_bundle.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,9 +861,9 @@ def prepare_batches(self):
861861
self.batchwise_valuation_batches = []
862862
self.non_batchwise_valuation_batches = []
863863

864-
if get_valuation_method(self.sle.item_code) == "Moving Average" and frappe.get_single_value(
865-
"Stock Settings", "do_not_use_batchwise_valuation"
866-
):
864+
if get_valuation_method(
865+
self.sle.item_code, self.sle.company
866+
) == "Moving Average" and frappe.get_single_value("Stock Settings", "do_not_use_batchwise_valuation"):
867867
self.non_batchwise_valuation_batches = self.batches
868868
return
869869

0 commit comments

Comments
 (0)