diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.json b/erpnext/accounts/doctype/coupon_code/coupon_code.json index f88057fc3e8..930248ffe2b 100644 --- a/erpnext/accounts/doctype/coupon_code/coupon_code.json +++ b/erpnext/accounts/doctype/coupon_code/coupon_code.json @@ -13,6 +13,7 @@ "customer", "column_break_4", "coupon_code", + "from_external_ecomm_platform", "pricing_rule", "uses", "valid_from", @@ -61,11 +62,12 @@ "unique": 1 }, { + "depends_on": "eval !doc.from_external_ecomm_platform", "fieldname": "pricing_rule", "fieldtype": "Link", "label": "Pricing Rule", - "options": "Pricing Rule", - "reqd": 1 + "mandatory_depends_on": "eval: !doc.from_external_ecomm_platform", + "options": "Pricing Rule" }, { "fieldname": "uses", @@ -114,13 +116,20 @@ "options": "Coupon Code", "print_hide": 1, "read_only": 1 + }, + { + "default": "0", + "fieldname": "from_external_ecomm_platform", + "fieldtype": "Check", + "label": "From External Ecomm Platform" } ], "links": [], - "modified": "2024-03-27 13:06:47.220931", + "modified": "2024-06-28 06:17:01.833399", "modified_by": "Administrator", "module": "Accounts", "name": "Coupon Code", + "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { @@ -177,4 +186,4 @@ "states": [], "title_field": "coupon_name", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.py b/erpnext/accounts/doctype/coupon_code/coupon_code.py index 540011dd0ac..dd4bfa95792 100644 --- a/erpnext/accounts/doctype/coupon_code/coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/coupon_code.py @@ -23,8 +23,9 @@ class CouponCode(Document): coupon_type: DF.Literal["Promotional", "Gift Card"] customer: DF.Link | None description: DF.TextEditor | None + from_external_ecomm_platform: DF.Check maximum_use: DF.Int - pricing_rule: DF.Link + pricing_rule: DF.Link | None used: DF.Int valid_from: DF.Date | None valid_upto: DF.Date | None diff --git a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py index aad341e9e1d..293e3d2aa4b 100644 --- a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py @@ -142,3 +142,39 @@ class TestCouponCode(unittest.TestCase): so.submit() self.assertEqual(frappe.db.get_value("Coupon Code", "SAVE30", "used"), 1) + + def test_coupon_without_max_use(self): + from erpnext.accounts.doctype.pricing_rule.utils import ( + update_coupon_code_count, + validate_coupon_code, + ) + + coupon = frappe.get_doc( + { + "doctype": "Coupon Code", + "coupon_name": "_Test Coupon Without Max Use", + "coupon_code": "TESTUNLIMITED", + "from_external_ecomm_platform": 1, # avoids requirement for pricing rule + "valid_from": frappe.utils.nowdate(), + "maximum_use": 0, + "used": 0, + } + ) + coupon.insert(ignore_permissions=True) + + # Validate initial state + self.assertEqual(coupon.used, 0) + self.assertEqual(coupon.maximum_use, 0) + + # Use coupon multiple times + for _ in range(5): + validate_coupon_code(coupon.name) + update_coupon_code_count(coupon.name, "used") + coupon.reload() + + # Check that the coupon is still valid and usage count increased + self.assertEqual(coupon.used, 5) + validate_coupon_code(coupon.name) # This should not raise an error + + # Clean up + coupon.delete() diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index ec83d650c4a..aa6bce6696c 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -731,7 +731,7 @@ def validate_coupon_code(coupon_name): elif coupon.valid_upto: if coupon.valid_upto < getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has expired")) - elif coupon.used >= coupon.maximum_use: + elif coupon.maximum_use and coupon.used >= coupon.maximum_use: frappe.throw(_("Sorry, this coupon code is no longer valid")) @@ -739,7 +739,10 @@ def update_coupon_code_count(coupon_name, transaction_type): coupon = frappe.get_doc("Coupon Code", coupon_name) if coupon: if transaction_type == "used": - if coupon.used < coupon.maximum_use: + if not coupon.maximum_use: + coupon.used = coupon.used + 1 + coupon.save(ignore_permissions=True) + elif coupon.used < coupon.maximum_use: coupon.used = coupon.used + 1 coupon.save(ignore_permissions=True) else: