Merge pull request #28398 from rohitwaghchaure/fix-pricing-rule-creation-against-promotional-scheme
fix: Pricing Rule not created against the Promotional Scheme
This commit is contained in:
commit
aaf0e4e709
@ -20,6 +20,9 @@ price_discount_fields = ['rate_or_discount', 'apply_discount_on', 'apply_discoun
|
|||||||
product_discount_fields = ['free_item', 'free_qty', 'free_item_uom',
|
product_discount_fields = ['free_item', 'free_qty', 'free_item_uom',
|
||||||
'free_item_rate', 'same_item', 'is_recursive', 'apply_multiple_pricing_rules']
|
'free_item_rate', 'same_item', 'is_recursive', 'apply_multiple_pricing_rules']
|
||||||
|
|
||||||
|
class TransactionExists(frappe.ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
class PromotionalScheme(Document):
|
class PromotionalScheme(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if not self.selling and not self.buying:
|
if not self.selling and not self.buying:
|
||||||
@ -28,6 +31,40 @@ class PromotionalScheme(Document):
|
|||||||
or self.product_discount_slabs):
|
or self.product_discount_slabs):
|
||||||
frappe.throw(_("Price or product discount slabs are required"))
|
frappe.throw(_("Price or product discount slabs are required"))
|
||||||
|
|
||||||
|
self.validate_applicable_for()
|
||||||
|
self.validate_pricing_rules()
|
||||||
|
|
||||||
|
def validate_applicable_for(self):
|
||||||
|
if self.applicable_for:
|
||||||
|
applicable_for = frappe.scrub(self.applicable_for)
|
||||||
|
|
||||||
|
if not self.get(applicable_for):
|
||||||
|
msg = (f'The field {frappe.bold(self.applicable_for)} is required')
|
||||||
|
frappe.throw(_(msg))
|
||||||
|
|
||||||
|
def validate_pricing_rules(self):
|
||||||
|
if self.is_new():
|
||||||
|
return
|
||||||
|
|
||||||
|
transaction_exists = False
|
||||||
|
docnames = []
|
||||||
|
|
||||||
|
# If user has changed applicable for
|
||||||
|
if self._doc_before_save.applicable_for == self.applicable_for:
|
||||||
|
return
|
||||||
|
|
||||||
|
docnames = frappe.get_all('Pricing Rule',
|
||||||
|
filters= {'promotional_scheme': self.name})
|
||||||
|
|
||||||
|
for docname in docnames:
|
||||||
|
if frappe.db.exists('Pricing Rule Detail',
|
||||||
|
{'pricing_rule': docname.name, 'docstatus': ('<', 2)}):
|
||||||
|
raise_for_transaction_exists(self.name)
|
||||||
|
|
||||||
|
if docnames and not transaction_exists:
|
||||||
|
for docname in docnames:
|
||||||
|
frappe.delete_doc('Pricing Rule', docname.name)
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
pricing_rules = frappe.get_all(
|
pricing_rules = frappe.get_all(
|
||||||
'Pricing Rule',
|
'Pricing Rule',
|
||||||
@ -67,6 +104,13 @@ class PromotionalScheme(Document):
|
|||||||
{'promotional_scheme': self.name}):
|
{'promotional_scheme': self.name}):
|
||||||
frappe.delete_doc('Pricing Rule', rule.name)
|
frappe.delete_doc('Pricing Rule', rule.name)
|
||||||
|
|
||||||
|
def raise_for_transaction_exists(name):
|
||||||
|
msg = (f"""You can't change the {frappe.bold(_('Applicable For'))}
|
||||||
|
because transactions are present against the Promotional Scheme {frappe.bold(name)}. """)
|
||||||
|
msg += 'Kindly disable this Promotional Scheme and create new for new Applicable For.'
|
||||||
|
|
||||||
|
frappe.throw(_(msg), TransactionExists)
|
||||||
|
|
||||||
def get_pricing_rules(doc, rules=None):
|
def get_pricing_rules(doc, rules=None):
|
||||||
if rules is None:
|
if rules is None:
|
||||||
rules = {}
|
rules = {}
|
||||||
@ -84,45 +128,59 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None):
|
|||||||
new_doc = []
|
new_doc = []
|
||||||
args = get_args_for_pricing_rule(doc)
|
args = get_args_for_pricing_rule(doc)
|
||||||
applicable_for = frappe.scrub(doc.get('applicable_for'))
|
applicable_for = frappe.scrub(doc.get('applicable_for'))
|
||||||
|
|
||||||
for idx, d in enumerate(doc.get(child_doc)):
|
for idx, d in enumerate(doc.get(child_doc)):
|
||||||
if d.name in rules:
|
if d.name in rules:
|
||||||
for applicable_for_value in args.get(applicable_for):
|
if not args.get(applicable_for):
|
||||||
temp_args = args.copy()
|
docname = get_pricing_rule_docname(d)
|
||||||
docname = frappe.get_all(
|
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d, docname)
|
||||||
'Pricing Rule',
|
new_doc.append(pr)
|
||||||
fields = ["promotional_scheme_id", "name", applicable_for],
|
|
||||||
filters = {
|
|
||||||
'promotional_scheme_id': d.name,
|
|
||||||
applicable_for: applicable_for_value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if docname:
|
|
||||||
pr = frappe.get_doc('Pricing Rule', docname[0].get('name'))
|
|
||||||
temp_args[applicable_for] = applicable_for_value
|
|
||||||
pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
|
|
||||||
else:
|
else:
|
||||||
pr = frappe.new_doc("Pricing Rule")
|
for applicable_for_value in args.get(applicable_for):
|
||||||
pr.title = doc.name
|
docname = get_pricing_rule_docname(d, applicable_for, applicable_for_value)
|
||||||
temp_args[applicable_for] = applicable_for_value
|
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
|
||||||
pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
|
d, docname, applicable_for, applicable_for_value)
|
||||||
|
|
||||||
new_doc.append(pr)
|
new_doc.append(pr)
|
||||||
|
|
||||||
else:
|
elif args.get(applicable_for):
|
||||||
applicable_for_values = args.get(applicable_for) or []
|
applicable_for_values = args.get(applicable_for) or []
|
||||||
for applicable_for_value in applicable_for_values:
|
for applicable_for_value in applicable_for_values:
|
||||||
pr = frappe.new_doc("Pricing Rule")
|
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
|
||||||
pr.title = doc.name
|
d, applicable_for=applicable_for, value= applicable_for_value)
|
||||||
temp_args = args.copy()
|
|
||||||
temp_args[applicable_for] = applicable_for_value
|
new_doc.append(pr)
|
||||||
pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
|
else:
|
||||||
|
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d)
|
||||||
new_doc.append(pr)
|
new_doc.append(pr)
|
||||||
|
|
||||||
return new_doc
|
return new_doc
|
||||||
|
|
||||||
|
def get_pricing_rule_docname(row: dict, applicable_for: str = None, applicable_for_value: str = None) -> str:
|
||||||
|
fields = ['promotional_scheme_id', 'name']
|
||||||
|
filters = {
|
||||||
|
'promotional_scheme_id': row.name
|
||||||
|
}
|
||||||
|
|
||||||
|
if applicable_for:
|
||||||
|
fields.append(applicable_for)
|
||||||
|
filters[applicable_for] = applicable_for_value
|
||||||
|
|
||||||
|
docname = frappe.get_all('Pricing Rule', fields = fields, filters = filters)
|
||||||
|
return docname[0].name if docname else ''
|
||||||
|
|
||||||
|
def prepare_pricing_rule(args, doc, child_doc, discount_fields, d, docname=None, applicable_for=None, value=None):
|
||||||
|
if docname:
|
||||||
|
pr = frappe.get_doc("Pricing Rule", docname)
|
||||||
|
else:
|
||||||
|
pr = frappe.new_doc("Pricing Rule")
|
||||||
|
|
||||||
|
pr.title = doc.name
|
||||||
|
temp_args = args.copy()
|
||||||
|
|
||||||
|
if value:
|
||||||
|
temp_args[applicable_for] = value
|
||||||
|
|
||||||
|
return set_args(temp_args, pr, doc, child_doc, discount_fields, d)
|
||||||
|
|
||||||
def set_args(args, pr, doc, child_doc, discount_fields, child_doc_fields):
|
def set_args(args, pr, doc, child_doc, discount_fields, child_doc_fields):
|
||||||
pr.update(args)
|
pr.update(args)
|
||||||
@ -145,6 +203,7 @@ def set_args(args, pr, doc, child_doc, discount_fields, child_doc_fields):
|
|||||||
apply_on: d.get(apply_on),
|
apply_on: d.get(apply_on),
|
||||||
'uom': d.uom
|
'uom': d.uom
|
||||||
})
|
})
|
||||||
|
|
||||||
return pr
|
return pr
|
||||||
|
|
||||||
def get_args_for_pricing_rule(doc):
|
def get_args_for_pricing_rule(doc):
|
||||||
|
@ -5,10 +5,17 @@ import unittest
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.promotional_scheme.promotional_scheme import TransactionExists
|
||||||
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
|
|
||||||
|
|
||||||
class TestPromotionalScheme(unittest.TestCase):
|
class TestPromotionalScheme(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
if frappe.db.exists('Promotional Scheme', '_Test Scheme'):
|
||||||
|
frappe.delete_doc('Promotional Scheme', '_Test Scheme')
|
||||||
|
|
||||||
def test_promotional_scheme(self):
|
def test_promotional_scheme(self):
|
||||||
ps = make_promotional_scheme()
|
ps = make_promotional_scheme(applicable_for='Customer', customer='_Test Customer')
|
||||||
price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name", "creation"],
|
price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name", "creation"],
|
||||||
filters = {'promotional_scheme': ps.name})
|
filters = {'promotional_scheme': ps.name})
|
||||||
self.assertTrue(len(price_rules),1)
|
self.assertTrue(len(price_rules),1)
|
||||||
@ -39,22 +46,62 @@ class TestPromotionalScheme(unittest.TestCase):
|
|||||||
filters = {'promotional_scheme': ps.name})
|
filters = {'promotional_scheme': ps.name})
|
||||||
self.assertEqual(price_rules, [])
|
self.assertEqual(price_rules, [])
|
||||||
|
|
||||||
def make_promotional_scheme():
|
def test_promotional_scheme_without_applicable_for(self):
|
||||||
|
ps = make_promotional_scheme()
|
||||||
|
price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
|
||||||
|
|
||||||
|
self.assertTrue(len(price_rules), 1)
|
||||||
|
frappe.delete_doc('Promotional Scheme', ps.name)
|
||||||
|
|
||||||
|
price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
|
||||||
|
self.assertEqual(price_rules, [])
|
||||||
|
|
||||||
|
def test_change_applicable_for_in_promotional_scheme(self):
|
||||||
|
ps = make_promotional_scheme()
|
||||||
|
price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
|
||||||
|
self.assertTrue(len(price_rules), 1)
|
||||||
|
|
||||||
|
so = make_sales_order(qty=5, currency='USD', do_not_save=True)
|
||||||
|
so.set_missing_values()
|
||||||
|
so.save()
|
||||||
|
self.assertEqual(price_rules[0].name, so.pricing_rules[0].pricing_rule)
|
||||||
|
|
||||||
|
ps.applicable_for = 'Customer'
|
||||||
|
ps.append('customer', {
|
||||||
|
'customer': '_Test Customer'
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertRaises(TransactionExists, ps.save)
|
||||||
|
|
||||||
|
frappe.delete_doc('Sales Order', so.name)
|
||||||
|
frappe.delete_doc('Promotional Scheme', ps.name)
|
||||||
|
price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
|
||||||
|
self.assertEqual(price_rules, [])
|
||||||
|
|
||||||
|
def make_promotional_scheme(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
ps = frappe.new_doc('Promotional Scheme')
|
ps = frappe.new_doc('Promotional Scheme')
|
||||||
ps.name = '_Test Scheme'
|
ps.name = '_Test Scheme'
|
||||||
ps.append('items',{
|
ps.append('items',{
|
||||||
'item_code': '_Test Item'
|
'item_code': '_Test Item'
|
||||||
})
|
})
|
||||||
|
|
||||||
ps.selling = 1
|
ps.selling = 1
|
||||||
ps.append('price_discount_slabs',{
|
ps.append('price_discount_slabs',{
|
||||||
'min_qty': 4,
|
'min_qty': 4,
|
||||||
|
'validate_applied_rule': 0,
|
||||||
'discount_percentage': 20,
|
'discount_percentage': 20,
|
||||||
'rule_description': 'Test'
|
'rule_description': 'Test'
|
||||||
})
|
})
|
||||||
ps.applicable_for = 'Customer'
|
|
||||||
ps.append('customer',{
|
ps.company = '_Test Company'
|
||||||
'customer': "_Test Customer"
|
if args.applicable_for:
|
||||||
|
ps.applicable_for = args.applicable_for
|
||||||
|
ps.append(frappe.scrub(args.applicable_for), {
|
||||||
|
frappe.scrub(args.applicable_for): args.get(frappe.scrub(args.applicable_for))
|
||||||
})
|
})
|
||||||
|
|
||||||
ps.save()
|
ps.save()
|
||||||
|
|
||||||
return ps
|
return ps
|
||||||
|
@ -136,7 +136,7 @@
|
|||||||
"label": "Threshold for Suggestion"
|
"label": "Threshold for Suggestion"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "0",
|
||||||
"fieldname": "validate_applied_rule",
|
"fieldname": "validate_applied_rule",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Validate Applied Rule"
|
"label": "Validate Applied Rule"
|
||||||
@ -169,7 +169,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-19 15:49:29.598727",
|
"modified": "2021-11-16 00:25:33.843996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Promotional Scheme Price Discount",
|
"name": "Promotional Scheme Price Discount",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user