mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-22 14:39:19 +00:00
Merge pull request #42135 from blaggacao/feat/lpe-discretionary
feat(lpe): add discretionary reason
This commit is contained in:
@@ -15,14 +15,16 @@
|
|||||||
"purchase_amount",
|
"purchase_amount",
|
||||||
"expiry_date",
|
"expiry_date",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"company"
|
"company",
|
||||||
|
"discretionary_reason"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "loyalty_program",
|
"fieldname": "loyalty_program",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Loyalty Program",
|
"label": "Loyalty Program",
|
||||||
"options": "Loyalty Program"
|
"options": "Loyalty Program",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "loyalty_program_tier",
|
"fieldname": "loyalty_program_tier",
|
||||||
@@ -34,7 +36,8 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Customer",
|
"label": "Customer",
|
||||||
"options": "Customer"
|
"options": "Customer",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "redeem_against",
|
"fieldname": "redeem_against",
|
||||||
@@ -46,7 +49,8 @@
|
|||||||
"fieldname": "loyalty_points",
|
"fieldname": "loyalty_points",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Loyalty Points"
|
"label": "Loyalty Points",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "purchase_amount",
|
"fieldname": "purchase_amount",
|
||||||
@@ -57,24 +61,28 @@
|
|||||||
"fieldname": "expiry_date",
|
"fieldname": "expiry_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Expiry Date"
|
"label": "Expiry Date",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "posting_date",
|
"fieldname": "posting_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Posting Date"
|
"label": "Posting Date",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company"
|
"options": "Company",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "invoice_type",
|
"fieldname": "invoice_type",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Invoice Type",
|
"label": "Invoice Type",
|
||||||
"options": "DocType"
|
"options": "DocType",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "invoice",
|
"fieldname": "invoice",
|
||||||
@@ -82,11 +90,16 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Invoice",
|
"label": "Invoice",
|
||||||
"options": "invoice_type"
|
"options": "invoice_type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "discretionary_reason",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Discretionary Reason"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-03-27 13:10:03.015035",
|
"modified": "2024-07-01 08:51:13.927009",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Loyalty Point Entry",
|
"name": "Loyalty Point Entry",
|
||||||
|
|||||||
@@ -18,15 +18,16 @@ class LoyaltyPointEntry(Document):
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
company: DF.Link | None
|
company: DF.Link
|
||||||
customer: DF.Link | None
|
customer: DF.Link
|
||||||
expiry_date: DF.Date | None
|
discretionary_reason: DF.Data | None
|
||||||
|
expiry_date: DF.Date
|
||||||
invoice: DF.DynamicLink | None
|
invoice: DF.DynamicLink | None
|
||||||
invoice_type: DF.Link | None
|
invoice_type: DF.Link
|
||||||
loyalty_points: DF.Int
|
loyalty_points: DF.Int
|
||||||
loyalty_program: DF.Link | None
|
loyalty_program: DF.Link
|
||||||
loyalty_program_tier: DF.Data | None
|
loyalty_program_tier: DF.Data | None
|
||||||
posting_date: DF.Date | None
|
posting_date: DF.Date
|
||||||
purchase_amount: DF.Currency
|
purchase_amount: DF.Currency
|
||||||
redeem_against: DF.Link | None
|
redeem_against: DF.Link | None
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|||||||
@@ -3,6 +3,83 @@
|
|||||||
|
|
||||||
import unittest
|
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):
|
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
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"columns": 3,
|
||||||
"fieldname": "tier_name",
|
"fieldname": "tier_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"columns": 3,
|
||||||
"fieldname": "min_spent",
|
"fieldname": "min_spent",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@@ -28,6 +30,7 @@
|
|||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"columns": 3,
|
||||||
"description": "For how much spent = 1 Loyalty Point",
|
"description": "For how much spent = 1 Loyalty Point",
|
||||||
"fieldname": "collection_factor",
|
"fieldname": "collection_factor",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@@ -38,7 +41,7 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-09-05 07:41:25.694041",
|
"modified": "2024-09-06 09:26:03.323912",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Loyalty Program Collection",
|
"name": "Loyalty Program Collection",
|
||||||
|
|||||||
Reference in New Issue
Block a user