Merge pull request #32551 from codezart/subscription-plan-fix-months
fix: number of months subscription plan
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index ff84991..580838e 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -385,6 +385,7 @@
if self.docstatus == 2:
return
+ self.flags.cost_updated = False
existing_bom_cost = self.total_cost
if self.docstatus == 1:
@@ -407,7 +408,11 @@
frappe.get_doc("BOM", bom).update_cost(from_child_bom=True)
if not from_child_bom:
- frappe.msgprint(_("Cost Updated"), alert=True)
+ msg = "Cost Updated"
+ if not self.flags.cost_updated:
+ msg = "No changes in cost found"
+
+ frappe.msgprint(_(msg), alert=True)
def update_parent_cost(self):
if self.total_cost:
@@ -593,11 +598,16 @@
# not via doc event, table is not regenerated and needs updation
self.calculate_exploded_cost()
+ old_cost = self.total_cost
+
self.total_cost = self.operating_cost + self.raw_material_cost - self.scrap_material_cost
self.base_total_cost = (
self.base_operating_cost + self.base_raw_material_cost - self.base_scrap_material_cost
)
+ if self.total_cost != old_cost:
+ self.flags.cost_updated = True
+
def calculate_op_cost(self, update_hour_rate=False):
"""Update workstation rate and calculates totals"""
self.operating_cost = 0
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 27f3cc9..e34ac12 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -9,7 +9,10 @@
from frappe.tests.utils import FrappeTestCase
from frappe.utils import cstr, flt
-from erpnext.controllers.tests.test_subcontracting_controller import set_backflush_based_on
+from erpnext.controllers.tests.test_subcontracting_controller import (
+ make_stock_in_entry,
+ set_backflush_based_on,
+)
from erpnext.manufacturing.doctype.bom.bom import BOMRecursionError, item_query, make_variant_bom
from erpnext.manufacturing.doctype.bom_update_log.test_bom_update_log import (
update_cost_in_all_boms_in_test,
@@ -639,6 +642,28 @@
bom.submit()
self.assertEqual(bom.exploded_items[0].rate, bom.items[0].base_rate)
+ def test_bom_cost_update_flag(self):
+ rm_item = make_item(
+ properties={"is_stock_item": 1, "valuation_rate": 99, "last_purchase_rate": 89}
+ ).name
+ fg_item = make_item(properties={"is_stock_item": 1}).name
+
+ from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+
+ bom = make_bom(item=fg_item, raw_materials=[rm_item])
+
+ create_stock_reconciliation(
+ item_code=rm_item, warehouse="_Test Warehouse - _TC", qty=100, rate=600
+ )
+
+ bom.load_from_db()
+ bom.update_cost()
+ self.assertTrue(bom.flags.cost_updated)
+
+ bom.load_from_db()
+ bom.update_cost()
+ self.assertFalse(bom.flags.cost_updated)
+
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 9fb3be5..b8c5187 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -13,6 +13,8 @@
import erpnext
from erpnext.stock.valuation import FIFOValuation, LIFOValuation
+BarcodeScanResult = Dict[str, Optional[str]]
+
class InvalidWarehouseCompany(frappe.ValidationError):
pass
@@ -552,7 +554,16 @@
@frappe.whitelist()
-def scan_barcode(search_value: str) -> Dict[str, Optional[str]]:
+def scan_barcode(search_value: str) -> BarcodeScanResult:
+ def set_cache(data: BarcodeScanResult):
+ frappe.cache().set_value(f"erpnext:barcode_scan:{search_value}", data, expires_in_sec=120)
+
+ def get_cache() -> Optional[BarcodeScanResult]:
+ if data := frappe.cache().get_value(f"erpnext:barcode_scan:{search_value}"):
+ return data
+
+ if scan_data := get_cache():
+ return scan_data
# search barcode no
barcode_data = frappe.db.get_value(
@@ -562,7 +573,9 @@
as_dict=True,
)
if barcode_data:
- return _update_item_info(barcode_data)
+ _update_item_info(barcode_data)
+ set_cache(barcode_data)
+ return barcode_data
# search serial no
serial_no_data = frappe.db.get_value(
@@ -572,7 +585,9 @@
as_dict=True,
)
if serial_no_data:
- return _update_item_info(serial_no_data)
+ _update_item_info(serial_no_data)
+ set_cache(serial_no_data)
+ return serial_no_data
# search batch no
batch_no_data = frappe.db.get_value(
@@ -582,7 +597,9 @@
as_dict=True,
)
if batch_no_data:
- return _update_item_info(batch_no_data)
+ _update_item_info(batch_no_data)
+ set_cache(batch_no_data)
+ return batch_no_data
return {}