mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 17:04:47 +00:00
[ Major ] Loyalty Program Fixes (#14863)
* fix checking of customer_group & territory of customer in loyalty program * fetch and set applicable loyalty program - in customer.py if found 1 program, set it or show a message to set it manually - in sales invoice, if found 1 program for selected customer with no program set, set it else open a dialog with applicable options * removed disabled field, added from_date & to_date * loyalty program section made collapsible, added redeem check in it * setting loyalty program improvised, manual selection if multiple found * get_query added, amount calculation updated * args passed rectified for expiry_date * get loyalty_points logic improv, redemption_details logic added * improv based on from/to date and other rectification * code rectified based on different scenarios - is_return, cancel, make loyalty points entry improv
This commit is contained in:
@@ -13,15 +13,22 @@ class LoyaltyPointEntry(Document):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_loyalty_point_entries(customer, loyalty_program, expiry_date=None, company=None):
|
def get_loyalty_point_entries(customer, loyalty_program, company, expiry_date=None):
|
||||||
if not expiry_date:
|
if not expiry_date:
|
||||||
date = today()
|
date = today()
|
||||||
args_list = [customer, loyalty_program, expiry_date]
|
|
||||||
condition = ''
|
return frappe.db.sql('''
|
||||||
if company:
|
select name, loyalty_points, expiry_date, loyalty_program_tier
|
||||||
condition = " and company=%s "
|
from `tabLoyalty Point Entry`
|
||||||
args_list.append(company)
|
where customer=%s and loyalty_program=%s
|
||||||
loyalty_point_details = frappe.db.sql('''select name, loyalty_points, expiry_date, loyalty_program_tier
|
and expiry_date>=%s and loyalty_points>0 and company=%s
|
||||||
from `tabLoyalty Point Entry` where customer=%s and loyalty_program=%s and expiry_date>=%s and loyalty_points>0
|
order by expiry_date
|
||||||
{condition} order by expiry_date'''.format(condition=condition), tuple(args_list), as_dict=1)
|
''', (customer, loyalty_program, expiry_date, company), as_dict=1)
|
||||||
return loyalty_point_details
|
|
||||||
|
def get_redemption_details(customer, loyalty_program, company):
|
||||||
|
return frappe._dict(frappe.db.sql('''
|
||||||
|
select redeem_against, sum(loyalty_points)
|
||||||
|
from `tabLoyalty Point Entry`
|
||||||
|
where customer=%s and loyalty_program=%s and loyalty_points<0 and company=%s
|
||||||
|
group by redeem_against
|
||||||
|
''', (customer, loyalty_program, company)))
|
||||||
|
|||||||
@@ -15,128 +15,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_in_quick_entry": 0,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "disabled",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Disabled",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_2",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "auto_opt_in",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Auto Opt In (For all customers)",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_2",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -164,10 +43,11 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -200,6 +80,72 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "from_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "From Date",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "to_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "To Date",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -230,6 +176,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -262,6 +209,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -294,6 +242,39 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "auto_opt_in",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Auto Opt In (For all customers)",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -325,6 +306,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -357,6 +339,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -388,6 +371,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -420,6 +404,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -451,6 +436,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -481,6 +467,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -513,6 +500,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -545,6 +533,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -577,6 +566,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -608,6 +598,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -648,7 +639,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-03-21 10:20:25.468206",
|
"modified": "2018-07-10 19:15:24.994385",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Loyalty Program",
|
"name": "Loyalty Program",
|
||||||
@@ -657,7 +648,6 @@
|
|||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
@@ -683,5 +673,6 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
}
|
}
|
||||||
@@ -16,14 +16,17 @@ class LoyaltyProgram(Document):
|
|||||||
def get_loyalty_details(customer, loyalty_program, expiry_date=None, company=None):
|
def get_loyalty_details(customer, loyalty_program, expiry_date=None, company=None):
|
||||||
if not expiry_date:
|
if not expiry_date:
|
||||||
expiry_date = today()
|
expiry_date = today()
|
||||||
args_list = [customer, loyalty_program, expiry_date]
|
|
||||||
|
args_list = [customer, loyalty_program, expiry_date, expiry_date]
|
||||||
condition = ''
|
condition = ''
|
||||||
if company:
|
if company:
|
||||||
condition = " and company=%s "
|
condition = " and company=%s "
|
||||||
args_list.append(company)
|
args_list.append(company)
|
||||||
loyalty_point_details = frappe.db.sql('''select sum(loyalty_points) as loyalty_points,
|
loyalty_point_details = frappe.db.sql('''select sum(loyalty_points) as loyalty_points,
|
||||||
sum(purchase_amount) as total_spent from `tabLoyalty Point Entry`
|
sum(purchase_amount) as total_spent from `tabLoyalty Point Entry`
|
||||||
where customer=%s and loyalty_program=%s and (expiry_date>=%s) {condition}
|
where customer=%s and loyalty_program=%s
|
||||||
|
and expiry_date>=%s and posting_date <= %s
|
||||||
|
{condition}
|
||||||
group by customer'''.format(condition=condition), tuple(args_list), as_dict=1)
|
group by customer'''.format(condition=condition), tuple(args_list), as_dict=1)
|
||||||
if loyalty_point_details:
|
if loyalty_point_details:
|
||||||
return loyalty_point_details[0]
|
return loyalty_point_details[0]
|
||||||
@@ -33,35 +36,28 @@ def get_loyalty_details(customer, loyalty_program, expiry_date=None, company=Non
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_loyalty_program_details(customer, loyalty_program=None, expiry_date=None, company=None, silent=False):
|
def get_loyalty_program_details(customer, loyalty_program=None, expiry_date=None, company=None, silent=False):
|
||||||
lp_details = frappe._dict()
|
lp_details = frappe._dict()
|
||||||
customer_loyalty_program = frappe.db.get_value("Customer", customer, "loyalty_program")
|
|
||||||
|
|
||||||
if not (customer_loyalty_program or silent):
|
|
||||||
frappe.throw(_("Customer isn't enrolled in any Loyalty Program"))
|
|
||||||
elif silent and not customer_loyalty_program:
|
|
||||||
return frappe._dict({"loyalty_program": None})
|
|
||||||
|
|
||||||
if loyalty_program and loyalty_program != customer_loyalty_program:
|
|
||||||
frappe.throw(_("Customer isn't enrolled in this Loyalty Program"))
|
|
||||||
|
|
||||||
if not loyalty_program:
|
if not loyalty_program:
|
||||||
loyalty_program = customer_loyalty_program
|
loyalty_program = frappe.db.get_value("Customer", customer, "loyalty_program")
|
||||||
|
|
||||||
|
if not (loyalty_program or silent):
|
||||||
|
frappe.throw(_("Customer isn't enrolled in any Loyalty Program"))
|
||||||
|
elif silent and not loyalty_program:
|
||||||
|
return frappe._dict({"loyalty_program": None})
|
||||||
|
|
||||||
if not company:
|
if not company:
|
||||||
company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name
|
company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name
|
||||||
|
|
||||||
lp_details.update(get_loyalty_details(customer, loyalty_program, expiry_date, company))
|
loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program)
|
||||||
|
lp_details.update({"loyalty_program": loyalty_program.name})
|
||||||
|
lp_details.update(loyalty_program.as_dict())
|
||||||
|
|
||||||
lp_details.update({"loyalty_program": loyalty_program})
|
lp_details.update(get_loyalty_details(customer, loyalty_program.name, expiry_date, company))
|
||||||
loyalty_program = frappe.get_doc("Loyalty Program", lp_details.loyalty_program)
|
|
||||||
|
|
||||||
lp_details.expiry_duration = loyalty_program.expiry_duration
|
tier_spent_level = sorted([d.as_dict() for d in loyalty_program.collection_rules],
|
||||||
lp_details.conversion_factor = loyalty_program.conversion_factor
|
key=lambda rule:rule.min_spent, reverse=True)
|
||||||
lp_details.expense_account = loyalty_program.expense_account
|
|
||||||
lp_details.cost_center = loyalty_program.cost_center
|
|
||||||
lp_details.company = loyalty_program.company
|
|
||||||
|
|
||||||
tier_spent_level = sorted([d.as_dict() for d in loyalty_program.collection_rules], key=lambda rule:rule.min_spent, reverse=True)
|
|
||||||
for i, d in enumerate(tier_spent_level):
|
for i, d in enumerate(tier_spent_level):
|
||||||
if i==0 or lp_details.total_spent < d.min_spent:
|
if i == 0 or lp_details.total_spent < d.min_spent:
|
||||||
lp_details.tier_name = d.tier_name
|
lp_details.tier_name = d.tier_name
|
||||||
lp_details.collection_factor = d.collection_factor
|
lp_details.collection_factor = d.collection_factor
|
||||||
else:
|
else:
|
||||||
@@ -122,4 +118,4 @@ def validate_loyalty_points(ref_doc, points_to_redeem):
|
|||||||
ref_doc.loyalty_redemption_cost_center = loyalty_program_details.cost_center
|
ref_doc.loyalty_redemption_cost_center = loyalty_program_details.cost_center
|
||||||
|
|
||||||
elif ref_doc.doctype == "Sales Order":
|
elif ref_doc.doctype == "Sales Order":
|
||||||
return loyalty_amount
|
return loyalty_amount
|
||||||
|
|||||||
@@ -230,6 +230,20 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
}, function() {
|
}, function() {
|
||||||
me.apply_pricing_rule();
|
me.apply_pricing_rule();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(this.frm.doc.customer) {
|
||||||
|
frappe.call({
|
||||||
|
"method": "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_loyalty_programs",
|
||||||
|
"args": {
|
||||||
|
"customer": this.frm.doc.customer
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(r.message) {
|
||||||
|
select_loyalty_program(me.frm, r.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
make_inter_company_invoice: function() {
|
make_inter_company_invoice: function() {
|
||||||
@@ -530,10 +544,6 @@ cur_frm.set_query("asset", "items", function(doc, cdt, cdn) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Sales Invoice', {
|
frappe.ui.form.on('Sales Invoice', {
|
||||||
refresh: function(frm) {
|
|
||||||
frm.add_fetch('customer', 'loyalty_program', 'loyalty_program');
|
|
||||||
},
|
|
||||||
|
|
||||||
setup: function(frm){
|
setup: function(frm){
|
||||||
|
|
||||||
frm.custom_make_buttons = {
|
frm.custom_make_buttons = {
|
||||||
@@ -598,6 +608,24 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// set get_query for loyalty redemption account
|
||||||
|
frm.fields_dict["loyalty_redemption_account"].get_query = function() {
|
||||||
|
return {
|
||||||
|
filters:{
|
||||||
|
"company": frm.doc.company
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// set get_query for loyalty redemption cost center
|
||||||
|
frm.fields_dict["loyalty_redemption_cost_center"].get_query = function() {
|
||||||
|
return {
|
||||||
|
filters:{
|
||||||
|
"company": frm.doc.company
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
//When multiple companies are set up. in case company name is changed set default company address
|
//When multiple companies are set up. in case company name is changed set default company address
|
||||||
company:function(frm){
|
company:function(frm){
|
||||||
@@ -661,18 +689,15 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
|
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
|
||||||
args: {
|
args: {
|
||||||
"customer": frm.doc.customer,
|
"customer": frm.doc.customer,
|
||||||
"till_date": frm.doc.posting_date,
|
"loyalty_program": frm.doc.loyalty_program,
|
||||||
|
"expiry_date": frm.doc.posting_date,
|
||||||
"company": frm.doc.company
|
"company": frm.doc.company
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r) {
|
if (r) {
|
||||||
frm.set_value("loyalty_program", r.message.loyalty_program);
|
|
||||||
frm.set_value("loyalty_redemption_account", r.message.expense_account);
|
frm.set_value("loyalty_redemption_account", r.message.expense_account);
|
||||||
frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
|
frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
|
||||||
frm.redemption_conversion_factor = r.message.conversion_factor;
|
frm.redemption_conversion_factor = r.message.conversion_factor;
|
||||||
// let max_loyalty_points = parseInt((frm.doc.grand_total-frm.doc.total_advance)/r.message.conversion_factor);
|
|
||||||
// let redeemable_points = max_loyalty_points > r.message.loyalty_points ? r.message.loyalty_points : max_loyalty_points;
|
|
||||||
// frm.set_value("loyalty_points", redeemable_points);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -682,10 +707,10 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
set_loyalty_points: function(frm) {
|
set_loyalty_points: function(frm) {
|
||||||
if (frm.redemption_conversion_factor) {
|
if (frm.redemption_conversion_factor) {
|
||||||
let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount"));
|
let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount"));
|
||||||
var remaining_amount = flt(frm.doc.grand_total - frm.doc.total_advance)
|
var remaining_amount = flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount);
|
||||||
if (frm.doc.grand_total && (remaining_amount < loyalty_amount)) {
|
if (frm.doc.grand_total && (remaining_amount < loyalty_amount)) {
|
||||||
let redeemable_amount = parseInt(remaining_amount/frm.redemption_conversion_factor);
|
let redeemable_points = parseInt(remaining_amount/frm.redemption_conversion_factor);
|
||||||
frappe.throw(__("You can only redeem max {0} points in this order.",[redeemable_amount]));
|
frappe.throw(__("You can only redeem max {0} points in this order.",[redeemable_points]));
|
||||||
}
|
}
|
||||||
frm.set_value("loyalty_amount", loyalty_amount);
|
frm.set_value("loyalty_amount", loyalty_amount);
|
||||||
}
|
}
|
||||||
@@ -729,3 +754,34 @@ var calculate_total_billing_amount = function(frm) {
|
|||||||
|
|
||||||
refresh_field('total_billing_amount')
|
refresh_field('total_billing_amount')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var select_loyalty_program = function(frm, loyalty_programs) {
|
||||||
|
var dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("Select Loyalty Program"),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
"label": __("Loyalty Program"),
|
||||||
|
"fieldname": "loyalty_program",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": loyalty_programs,
|
||||||
|
"default": loyalty_programs[0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.set_primary_action(__("Set"), function() {
|
||||||
|
dialog.hide();
|
||||||
|
return frappe.call({
|
||||||
|
method: "frappe.client.set_value",
|
||||||
|
args: {
|
||||||
|
doctype: "Customer",
|
||||||
|
name: frm.doc.customer,
|
||||||
|
fieldname: "loyalty_program",
|
||||||
|
value: dialog.get_value("loyalty_program"),
|
||||||
|
},
|
||||||
|
callback: function(r) { }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|||||||
@@ -381,38 +381,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "redeem_loyalty_points",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Redeem Loyalty Points",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -2460,10 +2428,10 @@
|
|||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 1,
|
||||||
"collapsible_depends_on": "",
|
"collapsible_depends_on": "",
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "redeem_loyalty_points",
|
"depends_on": "",
|
||||||
"fieldname": "loyalty_points_redemption",
|
"fieldname": "loyalty_points_redemption",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2496,6 +2464,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "redeem_loyalty_points",
|
||||||
"fieldname": "loyalty_points",
|
"fieldname": "loyalty_points",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2528,6 +2497,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "redeem_loyalty_points",
|
||||||
"fieldname": "loyalty_amount",
|
"fieldname": "loyalty_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2560,6 +2530,38 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fieldname": "redeem_loyalty_points",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Redeem Loyalty Points",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "column_break_77",
|
"fieldname": "column_break_77",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2591,6 +2593,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "",
|
||||||
|
"fetch_from": "customer.loyalty_program",
|
||||||
"fieldname": "loyalty_program",
|
"fieldname": "loyalty_program",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2624,6 +2628,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "redeem_loyalty_points",
|
||||||
"fieldname": "loyalty_redemption_account",
|
"fieldname": "loyalty_redemption_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2657,6 +2662,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "redeem_loyalty_points",
|
||||||
"fieldname": "loyalty_redemption_cost_center",
|
"fieldname": "loyalty_redemption_cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -5376,7 +5382,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2018-07-06 18:15:09.600814",
|
"modified": "2018-07-10 19:28:04.351108",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ class SalesInvoice(SellingController):
|
|||||||
elif self.is_return and self.return_against and self.loyalty_program:
|
elif self.is_return and self.return_against and self.loyalty_program:
|
||||||
against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
|
against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
|
||||||
against_si_doc.delete_loyalty_point_entry()
|
against_si_doc.delete_loyalty_point_entry()
|
||||||
|
against_si_doc.make_loyalty_point_entry()
|
||||||
if self.redeem_loyalty_points and self.loyalty_points:
|
if self.redeem_loyalty_points and self.loyalty_points:
|
||||||
self.apply_loyalty_points()
|
self.apply_loyalty_points()
|
||||||
|
|
||||||
@@ -209,6 +210,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.delete_loyalty_point_entry()
|
self.delete_loyalty_point_entry()
|
||||||
elif self.is_return and self.return_against and self.loyalty_program:
|
elif self.is_return and self.return_against and self.loyalty_program:
|
||||||
against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
|
against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
|
||||||
|
against_si_doc.delete_loyalty_point_entry()
|
||||||
against_si_doc.make_loyalty_point_entry()
|
against_si_doc.make_loyalty_point_entry()
|
||||||
|
|
||||||
unlink_inter_company_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
|
unlink_inter_company_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||||
@@ -967,24 +969,28 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
# collection of the loyalty points, create the ledger entry for that.
|
# collection of the loyalty points, create the ledger entry for that.
|
||||||
def make_loyalty_point_entry(self):
|
def make_loyalty_point_entry(self):
|
||||||
loyalty_program_details = get_loyalty_program_details(self.customer, company=self.company)
|
lp_details = get_loyalty_program_details(self.customer, company=self.company,
|
||||||
if loyalty_program_details:
|
loyalty_program=self.loyalty_program, expiry_date=self.posting_date)
|
||||||
points_earned = int(self.grand_total/loyalty_program_details.collection_factor)
|
if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
|
||||||
|
(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
|
||||||
|
returned_amount = self.get_returned_amount()
|
||||||
|
eligible_amount = flt(self.grand_total) - cint(self.loyalty_amount) - returned_amount
|
||||||
|
points_earned = cint(eligible_amount/lp_details.collection_factor)
|
||||||
doc = frappe.get_doc({
|
doc = frappe.get_doc({
|
||||||
"doctype": "Loyalty Point Entry",
|
"doctype": "Loyalty Point Entry",
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"loyalty_program": loyalty_program_details.loyalty_program,
|
"loyalty_program": lp_details.loyalty_program,
|
||||||
"loyalty_program_tier": loyalty_program_details.tier_name,
|
"loyalty_program_tier": lp_details.tier_name,
|
||||||
"customer": self.customer,
|
"customer": self.customer,
|
||||||
"sales_invoice": self.name,
|
"sales_invoice": self.name,
|
||||||
"loyalty_points": points_earned,
|
"loyalty_points": points_earned,
|
||||||
"purchase_amount": self.grand_total,
|
"purchase_amount": eligible_amount,
|
||||||
"expiry_date": add_days(self.posting_date, loyalty_program_details.expiry_duration),
|
"expiry_date": add_days(self.posting_date, lp_details.expiry_duration),
|
||||||
"posting_date": self.posting_date
|
"posting_date": self.posting_date
|
||||||
})
|
})
|
||||||
doc.flags.ignore_permissions = 1
|
doc.flags.ignore_permissions = 1
|
||||||
doc.save()
|
doc.save()
|
||||||
# frappe.db.set_value("Customer", self.customer, "loyalty_program_tier", loyalty_program_details.tier_name)
|
frappe.db.set_value("Customer", self.customer, "loyalty_program_tier", lp_details.tier_name)
|
||||||
|
|
||||||
# valdite the redemption and then delete the loyalty points earned on cancel of the invoice
|
# valdite the redemption and then delete the loyalty points earned on cancel of the invoice
|
||||||
def delete_loyalty_point_entry(self):
|
def delete_loyalty_point_entry(self):
|
||||||
@@ -998,19 +1004,33 @@ class SalesInvoice(SellingController):
|
|||||||
First cancel the Sales Invoice No {0}''').format(invoice_list))
|
First cancel the Sales Invoice No {0}''').format(invoice_list))
|
||||||
else:
|
else:
|
||||||
frappe.db.sql('''delete from `tabLoyalty Point Entry` where sales_invoice=%s''', (self.name))
|
frappe.db.sql('''delete from `tabLoyalty Point Entry` where sales_invoice=%s''', (self.name))
|
||||||
|
# Set loyalty program
|
||||||
|
lp_details = get_loyalty_program_details(self.customer, company=self.company,
|
||||||
|
loyalty_program=self.loyalty_program, expiry_date=self.posting_date)
|
||||||
|
frappe.db.set_value("Customer", self.customer, "loyalty_program_tier", lp_details.tier_name)
|
||||||
|
|
||||||
|
def get_returned_amount(self):
|
||||||
|
returned_amount = frappe.db.sql("""
|
||||||
|
select sum(grand_total)
|
||||||
|
from `tabSales Invoice`
|
||||||
|
where docstatus=1 and is_return=1 and ifnull(return_against, '')=%s
|
||||||
|
""", self.name)
|
||||||
|
return flt(returned_amount[0][0]) if returned_amount else 0
|
||||||
|
|
||||||
# redeem the loyalty points.
|
# redeem the loyalty points.
|
||||||
def apply_loyalty_points(self):
|
def apply_loyalty_points(self):
|
||||||
from erpnext.accounts.doctype.loyalty_point_entry.loyalty_point_entry \
|
from erpnext.accounts.doctype.loyalty_point_entry.loyalty_point_entry \
|
||||||
import get_loyalty_point_entries
|
import get_loyalty_point_entries, get_redemption_details
|
||||||
loyalty_point_entries = get_loyalty_point_entries(self.customer, self.loyalty_program, self.posting_date, self.company)
|
loyalty_point_entries = get_loyalty_point_entries(self.customer, self.loyalty_program, self.company, self.posting_date)
|
||||||
|
redemption_details = get_redemption_details(self.customer, self.loyalty_program, self.company)
|
||||||
|
|
||||||
points_to_redeem = self.loyalty_amount
|
points_to_redeem = self.loyalty_points
|
||||||
for lp_entry in loyalty_point_entries:
|
for lp_entry in loyalty_point_entries:
|
||||||
if lp_entry.loyalty_points > points_to_redeem:
|
available_points = lp_entry.loyalty_points - redemption_details.get(lp_entry.name)
|
||||||
|
if available_points > points_to_redeem:
|
||||||
redeemed_points = points_to_redeem
|
redeemed_points = points_to_redeem
|
||||||
else:
|
else:
|
||||||
redeemed_points = lp_entry.loyalty_points
|
redeemed_points = available_points
|
||||||
doc = frappe.get_doc({
|
doc = frappe.get_doc({
|
||||||
"doctype": "Loyalty Point Entry",
|
"doctype": "Loyalty Point Entry",
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
@@ -1019,7 +1039,7 @@ class SalesInvoice(SellingController):
|
|||||||
"customer": self.customer,
|
"customer": self.customer,
|
||||||
"sales_invoice": self.name,
|
"sales_invoice": self.name,
|
||||||
"redeem_against": lp_entry.name,
|
"redeem_against": lp_entry.name,
|
||||||
"loyalty_points": -(redeemed_points),
|
"loyalty_points": -1*redeemed_points,
|
||||||
"purchase_amount": self.grand_total,
|
"purchase_amount": self.grand_total,
|
||||||
"expiry_date": lp_entry.expiry_date,
|
"expiry_date": lp_entry.expiry_date,
|
||||||
"posting_date": self.posting_date
|
"posting_date": self.posting_date
|
||||||
@@ -1312,3 +1332,19 @@ def make_inter_company_invoice(doctype, source_name, target_doc=None):
|
|||||||
}, target_doc, set_missing_values)
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
return doclist
|
return doclist
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_loyalty_programs(customer):
|
||||||
|
''' sets applicable loyalty program to the customer or returns a list of applicable programs '''
|
||||||
|
from erpnext.selling.doctype.customer.customer import get_loyalty_programs
|
||||||
|
|
||||||
|
customer = frappe.get_doc('Customer', customer)
|
||||||
|
if customer.loyalty_program: return
|
||||||
|
|
||||||
|
lp_details = get_loyalty_programs(customer)
|
||||||
|
|
||||||
|
if len(lp_details) == 1:
|
||||||
|
frappe.db.set(customer, 'loyalty_program', lp_details[0])
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return lp_details
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import frappe
|
|||||||
from frappe.model.naming import set_name_by_naming_series
|
from frappe.model.naming import set_name_by_naming_series
|
||||||
from frappe import _, msgprint, throw
|
from frappe import _, msgprint, throw
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.utils import flt, cint, cstr
|
from frappe.utils import flt, cint, cstr, today
|
||||||
from frappe.desk.reportview import build_match_conditions, get_filters_cond
|
from frappe.desk.reportview import build_match_conditions, get_filters_cond
|
||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
|
from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
|
||||||
@@ -188,16 +188,33 @@ class Customer(TransactionBase):
|
|||||||
frappe.db.set(self, "customer_name", newdn)
|
frappe.db.set(self, "customer_name", newdn)
|
||||||
|
|
||||||
def set_loyalty_program(self):
|
def set_loyalty_program(self):
|
||||||
if not self.loyalty_program:
|
if self.loyalty_program: return
|
||||||
loyalty_programs = frappe.get_all("Loyalty Program", fields=["name", "customer_group",
|
loyalty_program = get_loyalty_programs(self)
|
||||||
"customer_territory"], filters={"auto_opt_in": 1, "disabled": 0})
|
if not loyalty_program: return
|
||||||
from frappe.desk.treeview import get_children
|
if len(loyalty_program) == 1:
|
||||||
for loyalty_program in loyalty_programs:
|
self.loyalty_program = loyalty_program[0]
|
||||||
customer_groups = get_children("Customer Group", loyalty_program.customer_group, )
|
else:
|
||||||
if self.customer_group in customer_groups and\
|
frappe.msgprint(_("Multiple Loyalty Program found for the Customer. Please select manually."))
|
||||||
self.territory in get_children("Territory", loyalty_program.customer_territory):
|
|
||||||
self.loyalty_program = loyalty_program.name
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_loyalty_programs(doc):
|
||||||
|
''' returns applicable loyalty programs for a customer '''
|
||||||
|
from frappe.desk.treeview import get_children
|
||||||
|
|
||||||
|
lp_details = []
|
||||||
|
loyalty_programs = frappe.get_all("Loyalty Program",
|
||||||
|
fields=["name", "customer_group", "customer_territory"],
|
||||||
|
filters={"auto_opt_in": 1, "from_date": ["<=", today()],
|
||||||
|
"ifnull(to_date, '2500-01-01')": [">=", today()]})
|
||||||
|
|
||||||
|
for loyalty_program in loyalty_programs:
|
||||||
|
customer_groups = [d.value for d in get_children("Customer Group", loyalty_program.customer_group)]
|
||||||
|
customer_territories = [d.value for d in get_children("Territory", loyalty_program.customer_territory)]
|
||||||
|
if (not loyalty_program.customer_group or doc.customer_group in customer_groups)\
|
||||||
|
and (not loyalty_program.customer_territory or doc.territory in customer_territories):
|
||||||
|
lp_details.append(loyalty_program.name)
|
||||||
|
|
||||||
|
return lp_details
|
||||||
|
|
||||||
def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
|
def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
|
||||||
if frappe.db.get_default("cust_master_name") == "Customer Name":
|
if frappe.db.get_default("cust_master_name") == "Customer Name":
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
|
method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
|
||||||
args: {
|
args: {
|
||||||
"customer": me.frm.doc.customer,
|
"customer": me.frm.doc.customer,
|
||||||
"till_date": me.frm.doc.posting_date,
|
"expiry_date": me.frm.doc.posting_date,
|
||||||
"company": me.frm.doc.company,
|
"company": me.frm.doc.company,
|
||||||
"silent": true
|
"silent": true
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user