mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-15 15:38:39 +00:00
refactor(stock): convert Item Price bulk update to qb
Replace the raw UPDATE ... modified=NOW() in update_item_price with frappe.qb.update (now() for modified). Same result on MariaDB; valid under Postgres. Tests: currency/buying/selling/modified propagation and price-list scoping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint
|
||||
from frappe.utils import cint, now
|
||||
|
||||
|
||||
class PriceList(Document):
|
||||
@@ -47,11 +47,15 @@ class PriceList(Document):
|
||||
frappe.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.name)
|
||||
|
||||
def update_item_price(self):
|
||||
frappe.db.sql(
|
||||
"""update `tabItem Price` set currency=%s,
|
||||
buying=%s, selling=%s, modified=NOW() where price_list=%s""",
|
||||
(self.currency, cint(self.buying), cint(self.selling), self.name),
|
||||
)
|
||||
item_price = frappe.qb.DocType("Item Price")
|
||||
(
|
||||
frappe.qb.update(item_price)
|
||||
.set(item_price.currency, self.currency)
|
||||
.set(item_price.buying, cint(self.buying))
|
||||
.set(item_price.selling, cint(self.selling))
|
||||
.set(item_price.modified, now())
|
||||
.where(item_price.price_list == self.name)
|
||||
).run()
|
||||
|
||||
def on_trash(self):
|
||||
self.delete_price_list_details_key()
|
||||
|
||||
@@ -1,4 +1,83 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe.utils import random_string
|
||||
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
|
||||
class TestPriceList(ERPNextTestSuite):
|
||||
def make_price_list(self, currency="INR", buying=1, selling=1):
|
||||
price_list = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "_Test PL " + random_string(10),
|
||||
"enabled": 1,
|
||||
"currency": currency,
|
||||
"buying": buying,
|
||||
"selling": selling,
|
||||
}
|
||||
).insert()
|
||||
return price_list
|
||||
|
||||
def make_item_price(self, price_list, item_code="_Test Item", rate=100):
|
||||
return frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"item_code": item_code,
|
||||
"price_list": price_list,
|
||||
"price_list_rate": rate,
|
||||
}
|
||||
).insert()
|
||||
|
||||
def test_update_item_price_propagates_currency_and_flags(self):
|
||||
# Price List starts in INR, applicable for both buying and selling.
|
||||
price_list = self.make_price_list(currency="INR", buying=1, selling=1)
|
||||
|
||||
ip1 = self.make_item_price(price_list.name, item_code="_Test Item", rate=100)
|
||||
ip2 = self.make_item_price(price_list.name, item_code="_Test Item 2", rate=250)
|
||||
|
||||
# Sanity: Item Price rows inherited the Price List's initial state.
|
||||
for ip in (ip1, ip2):
|
||||
row = frappe.db.get_value("Item Price", ip.name, ["currency", "buying", "selling"], as_dict=True)
|
||||
self.assertEqual(row.currency, "INR")
|
||||
self.assertEqual(row.buying, 1)
|
||||
self.assertEqual(row.selling, 1)
|
||||
|
||||
# Change the Price List's currency and flip the buying flag off.
|
||||
# on_update -> update_item_price() should bulk-UPDATE every Item Price
|
||||
# linked to this Price List.
|
||||
price_list.currency = "USD"
|
||||
price_list.buying = 0
|
||||
price_list.selling = 1
|
||||
price_list.save()
|
||||
|
||||
for ip in (ip1, ip2):
|
||||
row = frappe.db.get_value("Item Price", ip.name, ["currency", "buying", "selling"], as_dict=True)
|
||||
self.assertEqual(row.currency, "USD")
|
||||
self.assertEqual(row.buying, 0)
|
||||
self.assertEqual(row.selling, 1)
|
||||
|
||||
def test_update_item_price_scoped_to_own_price_list(self):
|
||||
# Two independent Price Lists; updating one must not touch the other's
|
||||
# Item Price rows (the WHERE price_list == self.name clause).
|
||||
pl_a = self.make_price_list(currency="INR", buying=1, selling=1)
|
||||
pl_b = self.make_price_list(currency="INR", buying=1, selling=1)
|
||||
|
||||
ip_a = self.make_item_price(pl_a.name, item_code="_Test Item", rate=100)
|
||||
ip_b = self.make_item_price(pl_b.name, item_code="_Test Item", rate=100)
|
||||
|
||||
pl_a.currency = "USD"
|
||||
pl_a.buying = 0
|
||||
pl_a.save()
|
||||
|
||||
row_a = frappe.db.get_value("Item Price", ip_a.name, ["currency", "buying"], as_dict=True)
|
||||
self.assertEqual(row_a.currency, "USD")
|
||||
self.assertEqual(row_a.buying, 0)
|
||||
|
||||
# pl_b was untouched, so its Item Price must keep the original values.
|
||||
row_b = frappe.db.get_value("Item Price", ip_b.name, ["currency", "buying"], as_dict=True)
|
||||
self.assertEqual(row_b.currency, "INR")
|
||||
self.assertEqual(row_b.buying, 1)
|
||||
|
||||
Reference in New Issue
Block a user