mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 17:04:47 +00:00
[shipping rule] validations and test cases
This commit is contained in:
@@ -3,23 +3,80 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
from webnotes import _, msgprint
|
from webnotes import _, msgprint
|
||||||
|
from webnotes.utils import flt, fmt_money
|
||||||
|
from webnotes.model.controller import DocListController
|
||||||
|
from setup.utils import get_company_currency
|
||||||
|
|
||||||
class DocType:
|
class OverlappingConditionError(webnotes.ValidationError): pass
|
||||||
|
class FromGreaterThanToError(webnotes.ValidationError): pass
|
||||||
|
class ManyBlankToValuesError(webnotes.ValidationError): pass
|
||||||
|
|
||||||
|
class DocType(DocListController):
|
||||||
def __init__(self, d, dl):
|
def __init__(self, d, dl):
|
||||||
self.doc, self.doclist = d, dl
|
self.doc, self.doclist = d, dl
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_to_value_of_shipping_rule_conditions()
|
self.shipping_rule_conditions = self.doclist.get({"parentfield": "shipping_rule_conditions"})
|
||||||
|
self.validate_from_to_values()
|
||||||
|
self.sort_shipping_rule_conditions()
|
||||||
self.validate_overlapping_shipping_rule_conditions()
|
self.validate_overlapping_shipping_rule_conditions()
|
||||||
|
|
||||||
|
def validate_from_to_values(self):
|
||||||
|
zero_to_values = []
|
||||||
|
|
||||||
def validate_to_value_of_shipping_rule_conditions(self):
|
for d in self.shipping_rule_conditions:
|
||||||
"""check if more than two or more rows has To Value = 0"""
|
self.round_floats_in(d)
|
||||||
shipping_rule_conditions_with_0_to_value = self.doclist.get({
|
|
||||||
"parentfield": "shipping_rule_conditions", "to_value": ["in", [0, None]]})
|
# values cannot be negative
|
||||||
if len(shipping_rule_conditions_with_0_to_value) >= 2:
|
self.validate_value("from_value", ">=", 0.0, d)
|
||||||
msgprint(_('''There can only be one shipping rule with 0 or blank value for "To Value"'''),
|
self.validate_value("to_value", ">=", 0.0, d)
|
||||||
raise_exception=True)
|
|
||||||
|
if d.to_value == 0:
|
||||||
|
zero_to_values.append(d)
|
||||||
|
elif d.from_value >= d.to_value:
|
||||||
|
msgprint(_("Error") + ": " + _("Row") + " # %d: " % d.idx +
|
||||||
|
_("From Value should be less than To Value"),
|
||||||
|
raise_exception=FromGreaterThanToError)
|
||||||
|
|
||||||
|
# check if more than two or more rows has To Value = 0
|
||||||
|
if len(zero_to_values) >= 2:
|
||||||
|
msgprint(_('''There can only be one Shipping Rule Condition with 0 or blank value for "To Value"'''),
|
||||||
|
raise_exception=ManyBlankToValuesError)
|
||||||
|
|
||||||
|
def sort_shipping_rule_conditions(self):
|
||||||
|
"""Sort Shipping Rule Conditions based on increasing From Value"""
|
||||||
|
self.shipping_rules_conditions = sorted(self.shipping_rule_conditions, key=lambda d: flt(d.from_value))
|
||||||
|
for i, d in enumerate(self.shipping_rule_conditions):
|
||||||
|
d.idx = i + 1
|
||||||
|
|
||||||
def validate_overlapping_shipping_rule_conditions(self):
|
def validate_overlapping_shipping_rule_conditions(self):
|
||||||
pass
|
def overlap_exists_between((x1, x2), (y1, y2)):
|
||||||
|
"""
|
||||||
|
(x1, x2) and (y1, y2) are two ranges
|
||||||
|
if condition x = 100 to 300
|
||||||
|
then condition y can only be like 50 to 99 or 301 to 400
|
||||||
|
hence, non-overlapping condition = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2)
|
||||||
|
"""
|
||||||
|
separate = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2)
|
||||||
|
return (not separate)
|
||||||
|
|
||||||
|
overlaps = []
|
||||||
|
for i in xrange(0, len(self.shipping_rule_conditions)):
|
||||||
|
for j in xrange(i+1, len(self.shipping_rule_conditions)):
|
||||||
|
d1, d2 = self.shipping_rule_conditions[i], self.shipping_rule_conditions[j]
|
||||||
|
if d1.fields != d2.fields:
|
||||||
|
# in our case, to_value can be zero, hence pass the from_value if so
|
||||||
|
range_a = (d1.from_value, d1.to_value or d1.from_value)
|
||||||
|
range_b = (d2.from_value, d2.to_value or d2.from_value)
|
||||||
|
if overlap_exists_between(range_a, range_b):
|
||||||
|
overlaps.append([d1, d2])
|
||||||
|
|
||||||
|
if overlaps:
|
||||||
|
company_currency = get_company_currency(self.doc.company)
|
||||||
|
msgprint(_("Error") + ": " + _("Overlapping Conditions found between") + ":")
|
||||||
|
messages = []
|
||||||
|
for d1, d2 in overlaps:
|
||||||
|
messages.append("%s-%s = %s " % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) +
|
||||||
|
_("and") + " %s-%s = %s" % (d2.from_value, d2.to_value, fmt_money(d2.shipping_amount, currency=company_currency)))
|
||||||
|
|
||||||
|
msgprint("\n".join(messages), raise_exception=OverlappingConditionError)
|
||||||
66
accounts/doctype/shipping_rule/test_shipping_rule.py
Normal file
66
accounts/doctype/shipping_rule/test_shipping_rule.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import webnotes
|
||||||
|
import unittest
|
||||||
|
from accounts.doctype.shipping_rule.shipping_rule import FromGreaterThanToError, ManyBlankToValuesError, OverlappingConditionError
|
||||||
|
|
||||||
|
class TestShippingRule(unittest.TestCase):
|
||||||
|
def test_from_greater_than_to(self):
|
||||||
|
shipping_rule = webnotes.bean(copy=test_records[0])
|
||||||
|
shipping_rule.doclist[1].from_value = 101
|
||||||
|
self.assertRaises(FromGreaterThanToError, shipping_rule.insert)
|
||||||
|
|
||||||
|
def test_many_zero_to_values(self):
|
||||||
|
shipping_rule = webnotes.bean(copy=test_records[0])
|
||||||
|
shipping_rule.doclist[1].to_value = 0
|
||||||
|
self.assertRaises(ManyBlankToValuesError, shipping_rule.insert)
|
||||||
|
|
||||||
|
def test_overlapping_conditions(self):
|
||||||
|
for range_a, range_b in [
|
||||||
|
((50, 150), (0, 100)),
|
||||||
|
((50, 150), (100, 200)),
|
||||||
|
((50, 150), (75, 125)),
|
||||||
|
((50, 150), (25, 175)),
|
||||||
|
((50, 150), (50, 150)),
|
||||||
|
]:
|
||||||
|
shipping_rule = webnotes.bean(copy=test_records[0])
|
||||||
|
shipping_rule.doclist[1].from_value = range_a[0]
|
||||||
|
shipping_rule.doclist[1].to_value = range_a[1]
|
||||||
|
shipping_rule.doclist[2].from_value = range_b[0]
|
||||||
|
shipping_rule.doclist[2].to_value = range_b[1]
|
||||||
|
self.assertRaises(OverlappingConditionError, shipping_rule.insert)
|
||||||
|
|
||||||
|
test_records = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"doctype": "Shipping Rule",
|
||||||
|
"calculate_based_on": "Amount",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"account": "_Test Account Shipping Charges - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Shipping Rule Condition",
|
||||||
|
"parentfield": "shipping_rule_conditions",
|
||||||
|
"from_value": 0,
|
||||||
|
"to_value": 100,
|
||||||
|
"shipping_amount": 50.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Shipping Rule Condition",
|
||||||
|
"parentfield": "shipping_rule_conditions",
|
||||||
|
"from_value": 101,
|
||||||
|
"to_value": 200,
|
||||||
|
"shipping_amount": 100.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Shipping Rule Condition",
|
||||||
|
"parentfield": "shipping_rule_conditions",
|
||||||
|
"from_value": 201,
|
||||||
|
"shipping_amount": 0.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "For Territory",
|
||||||
|
"parentfield": "valid_for_territories",
|
||||||
|
"territory": "_Test Territory"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user