diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json index 0d7c2e7c7f85..e2eecea1ee70 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json +++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json @@ -15,14 +15,16 @@ "purchase_amount", "expiry_date", "posting_date", - "company" + "company", + "discretionary_reason" ], "fields": [ { "fieldname": "loyalty_program", "fieldtype": "Link", "label": "Loyalty Program", - "options": "Loyalty Program" + "options": "Loyalty Program", + "reqd": 1 }, { "fieldname": "loyalty_program_tier", @@ -34,7 +36,8 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Customer", - "options": "Customer" + "options": "Customer", + "reqd": 1 }, { "fieldname": "redeem_against", @@ -46,7 +49,8 @@ "fieldname": "loyalty_points", "fieldtype": "Int", "in_list_view": 1, - "label": "Loyalty Points" + "label": "Loyalty Points", + "reqd": 1 }, { "fieldname": "purchase_amount", @@ -57,24 +61,28 @@ "fieldname": "expiry_date", "fieldtype": "Date", "in_list_view": 1, - "label": "Expiry Date" + "label": "Expiry Date", + "reqd": 1 }, { "fieldname": "posting_date", "fieldtype": "Date", - "label": "Posting Date" + "label": "Posting Date", + "reqd": 1 }, { "fieldname": "company", "fieldtype": "Link", "label": "Company", - "options": "Company" + "options": "Company", + "reqd": 1 }, { "fieldname": "invoice_type", "fieldtype": "Link", "label": "Invoice Type", - "options": "DocType" + "options": "DocType", + "reqd": 1 }, { "fieldname": "invoice", @@ -82,11 +90,16 @@ "in_list_view": 1, "label": "Invoice", "options": "invoice_type" + }, + { + "fieldname": "discretionary_reason", + "fieldtype": "Data", + "label": "Discretionary Reason" } ], "in_create": 1, "links": [], - "modified": "2024-03-27 13:10:03.015035", + "modified": "2024-07-01 08:51:13.927009", "modified_by": "Administrator", "module": "Accounts", "name": "Loyalty Point Entry", @@ -123,4 +136,4 @@ "states": [], "title_field": "customer", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py index eb8a06606d5a..5b4c0d2df3f7 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py +++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py @@ -18,15 +18,16 @@ class LoyaltyPointEntry(Document): if TYPE_CHECKING: from frappe.types import DF - company: DF.Link | None - customer: DF.Link | None - expiry_date: DF.Date | None + company: DF.Link + customer: DF.Link + discretionary_reason: DF.Data | None + expiry_date: DF.Date invoice: DF.DynamicLink | None - invoice_type: DF.Link | None + invoice_type: DF.Link loyalty_points: DF.Int - loyalty_program: DF.Link | None + loyalty_program: DF.Link loyalty_program_tier: DF.Data | None - posting_date: DF.Date | None + posting_date: DF.Date purchase_amount: DF.Currency redeem_against: DF.Link | None # end: auto-generated types diff --git a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py index cd38559d1d15..1042c46042d2 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py +++ b/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py @@ -3,6 +3,83 @@ import unittest +import frappe +from frappe.utils import today + +from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + class TestLoyaltyPointEntry(unittest.TestCase): - pass + @classmethod + def setUpClass(cls): + # Create test records + create_records() + cls.loyalty_program_name = "Test Single Loyalty" + cls.customer_name = "Test Loyalty Customer" + customer = frappe.get_doc("Customer", cls.customer_name) + customer.db_set("loyalty_program", cls.loyalty_program_name) + + @classmethod + def tearDownClass(cls): + # Delete all Loyalty Point Entries + frappe.db.sql("DELETE FROM `tabLoyalty Point Entry` WHERE customer = %s", cls.customer_name) + frappe.db.sql("DELETE FROM `tabSales Invoice` WHERE customer = %s", cls.customer_name) + frappe.db.commit() + # cls.customer.delete() + + def create_test_invoice(self, redeem=None): + if redeem: + si = create_sales_invoice(customer=self.customer_name, qty=1, rate=100, do_not_save=True) + si.redeem_loyalty_points = True + si.loyalty_points = redeem + return si.insert().submit() + else: + si = create_sales_invoice(customer=self.customer_name, qty=10, rate=1000, do_not_save=True) + return si.insert().submit() + + def test_add_loyalty_points(self): + self.create_test_invoice() + doc = frappe.get_last_doc("Loyalty Point Entry") + self.assertEqual(doc.loyalty_points, 10) + + def test_add_loyalty_points_with_discretionary_reason(self): + doc = frappe.get_doc( + { + "doctype": "Loyalty Point Entry", + "loyalty_program": "Test Single Loyalty", + "loyalty_program_tier": "Bronce", + "customer": self.customer_name, + "invoice_type": "Sales Invoice", + "loyalty_points": 75, + "expiry_date": today(), + "posting_date": today(), + "company": "_Test Company", + "discretionary_reason": "Customer Appreciation", + } + ) + doc.insert(ignore_permissions=True) + self.assertEqual(doc.loyalty_points, 75) + self.assertEqual(doc.discretionary_reason, "Customer Appreciation") + + # Verify the entry in the database + entry = frappe.get_doc("Loyalty Point Entry", doc.name) + self.assertEqual(entry.loyalty_points, 75) + self.assertEqual(entry.discretionary_reason, "Customer Appreciation") + + def test_redeem_loyalty_points(self): + self.create_test_invoice(redeem=10) + doc = frappe.get_last_doc("Loyalty Point Entry") + self.assertEqual(doc.loyalty_points, -10) + + # Check balance + balance = frappe.db.sql( + """ + SELECT SUM(loyalty_points) + FROM `tabLoyalty Point Entry` + WHERE customer = %s + """, + (self.customer_name,), + )[0][0] + + self.assertEqual(balance, 75) # 85 added, 10 redeemed diff --git a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.json b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.json index 3c1d73d120dc..cf064293f306 100644 --- a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.json +++ b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.json @@ -11,6 +11,7 @@ ], "fields": [ { + "columns": 3, "fieldname": "tier_name", "fieldtype": "Data", "in_list_view": 1, @@ -18,6 +19,7 @@ "reqd": 1 }, { + "columns": 3, "fieldname": "min_spent", "fieldtype": "Currency", "in_list_view": 1, @@ -28,6 +30,7 @@ "fieldtype": "Column Break" }, { + "columns": 3, "description": "For how much spent = 1 Loyalty Point", "fieldname": "collection_factor", "fieldtype": "Currency", @@ -38,7 +41,7 @@ ], "istable": 1, "links": [], - "modified": "2024-09-05 07:41:25.694041", + "modified": "2024-09-06 09:26:03.323912", "modified_by": "Administrator", "module": "Accounts", "name": "Loyalty Program Collection",