Browse Source

Merge pull request #28398 from rohitwaghchaure/fix-pricing-rule-creation-against-promotional-scheme

fix: Pricing Rule not created against the Promotional Scheme
develop
rohitwaghchaure 3 years ago
committed by GitHub
parent
commit
aaf0e4e709
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 113
      erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
  2. 59
      erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
  3. 4
      erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json

113
erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py

@ -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',
'free_item_rate', 'same_item', 'is_recursive', 'apply_multiple_pricing_rules']
class TransactionExists(frappe.ValidationError):
pass
class PromotionalScheme(Document):
def validate(self):
if not self.selling and not self.buying:
@ -28,6 +31,40 @@ class PromotionalScheme(Document):
or self.product_discount_slabs):
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):
pricing_rules = frappe.get_all(
'Pricing Rule',
@ -67,6 +104,13 @@ class PromotionalScheme(Document):
{'promotional_scheme': self.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):
if rules is None:
rules = {}
@ -84,45 +128,59 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None):
new_doc = []
args = get_args_for_pricing_rule(doc)
applicable_for = frappe.scrub(doc.get('applicable_for'))
for idx, d in enumerate(doc.get(child_doc)):
if d.name in rules:
for applicable_for_value in args.get(applicable_for):
temp_args = args.copy()
docname = frappe.get_all(
'Pricing Rule',
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:
pr = frappe.new_doc("Pricing Rule")
pr.title = doc.name
temp_args[applicable_for] = applicable_for_value
pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
if not args.get(applicable_for):
docname = get_pricing_rule_docname(d)
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d, docname)
new_doc.append(pr)
else:
for applicable_for_value in args.get(applicable_for):
docname = get_pricing_rule_docname(d, applicable_for, applicable_for_value)
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
d, docname, applicable_for, applicable_for_value)
new_doc.append(pr)
else:
elif args.get(applicable_for):
applicable_for_values = args.get(applicable_for) or []
for applicable_for_value in applicable_for_values:
pr = frappe.new_doc("Pricing Rule")
pr.title = doc.name
temp_args = args.copy()
temp_args[applicable_for] = applicable_for_value
pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
d, applicable_for=applicable_for, value= applicable_for_value)
new_doc.append(pr)
else:
pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d)
new_doc.append(pr)
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):
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),
'uom': d.uom
})
return pr
def get_args_for_pricing_rule(doc):

59
erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py

@ -5,10 +5,17 @@ import unittest
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):
def setUp(self):
if frappe.db.exists('Promotional Scheme', '_Test Scheme'):
frappe.delete_doc('Promotional Scheme', '_Test Scheme')
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"],
filters = {'promotional_scheme': ps.name})
self.assertTrue(len(price_rules),1)
@ -39,22 +46,62 @@ class TestPromotionalScheme(unittest.TestCase):
filters = {'promotional_scheme': ps.name})
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.name = '_Test Scheme'
ps.append('items',{
'item_code': '_Test Item'
})
ps.selling = 1
ps.append('price_discount_slabs',{
'min_qty': 4,
'validate_applied_rule': 0,
'discount_percentage': 20,
'rule_description': 'Test'
})
ps.applicable_for = 'Customer'
ps.append('customer',{
'customer': "_Test Customer"
})
ps.company = '_Test Company'
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()
return ps

4
erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json

@ -136,7 +136,7 @@
"label": "Threshold for Suggestion"
},
{
"default": "1",
"default": "0",
"fieldname": "validate_applied_rule",
"fieldtype": "Check",
"label": "Validate Applied Rule"
@ -169,7 +169,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-08-19 15:49:29.598727",
"modified": "2021-11-16 00:25:33.843996",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Promotional Scheme Price Discount",

Loading…
Cancel
Save