Merge branch 'develop' into fix-psoa-template
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
index 088c190..29f2e98 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
@@ -51,6 +51,13 @@
}
}
});
+ frm.set_query("account", function() {
+ return {
+ filters: {
+ 'company': frm.doc.company
+ }
+ };
+ });
if(frm.doc.__islocal){
frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1));
frm.set_value('to_date', frappe.datetime.get_today());
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 5062c1c..80b95db 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -2,7 +2,7 @@
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
- "creation": "2013-05-24 19:29:05",
+ "creation": "2022-01-25 10:29:57.771398",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
@@ -651,7 +651,6 @@
"hide_seconds": 1,
"label": "Ignore Pricing Rule",
"no_copy": 1,
- "permlevel": 0,
"print_hide": 1
},
{
@@ -1974,9 +1973,10 @@
},
{
"default": "0",
+ "description": "Issue a debit note with 0 qty against an existing Sales Invoice",
"fieldname": "is_debit_note",
"fieldtype": "Check",
- "label": "Is Debit Note"
+ "label": "Is Rate Adjustment Entry (Debit Note)"
},
{
"default": "0",
@@ -2038,7 +2038,7 @@
"link_fieldname": "consolidated_invoice"
}
],
- "modified": "2021-12-23 20:19:38.667508",
+ "modified": "2022-03-08 16:08:53.517903",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
@@ -2089,8 +2089,9 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"timeline_field": "customer",
"title_field": "title",
"track_changes": 1,
"track_seen": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset_dashboard.py b/erpnext/assets/doctype/asset/asset_dashboard.py
index 1833b0e..c81b611 100644
--- a/erpnext/assets/doctype/asset/asset_dashboard.py
+++ b/erpnext/assets/doctype/asset/asset_dashboard.py
@@ -1,5 +1,6 @@
from frappe import _
+
def get_data():
return {
'non_standard_fieldnames': {
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 874fb63..6e04242 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -23,7 +23,7 @@
frappe.db.commit()
def get_depreciable_assets(date):
- return frappe.db.sql_list("""select a.name
+ return frappe.db.sql_list("""select distinct a.name
from tabAsset a, `tabDepreciation Schedule` ds
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s and a.calculate_depreciation = 1
and a.status in ('Submitted', 'Partially Depreciated')
diff --git a/erpnext/e_commerce/api.py b/erpnext/e_commerce/api.py
index 43cb36c..84554ae 100644
--- a/erpnext/e_commerce/api.py
+++ b/erpnext/e_commerce/api.py
@@ -48,7 +48,6 @@
sub_categories = []
if item_group:
- field_filters['item_group'] = item_group
sub_categories = get_child_groups_for_website(item_group, immediate=True)
engine = ProductQuery()
diff --git a/erpnext/e_commerce/product_data_engine/filters.py b/erpnext/e_commerce/product_data_engine/filters.py
index c4a3cb9..89d4ffd 100644
--- a/erpnext/e_commerce/product_data_engine/filters.py
+++ b/erpnext/e_commerce/product_data_engine/filters.py
@@ -14,6 +14,8 @@
self.item_group = item_group
def get_field_filters(self):
+ from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website
+
if not self.item_group and not self.doc.enable_field_filters:
return
@@ -25,18 +27,26 @@
fields = [item_meta.get_field(field) for field in filter_fields if item_meta.has_field(field)]
for df in fields:
- item_filters, item_or_filters = {}, []
+ item_filters, item_or_filters = {"published_in_website": 1}, []
link_doctype_values = self.get_filtered_link_doctype_records(df)
if df.fieldtype == "Link":
if self.item_group:
- item_or_filters.extend([
- ["item_group", "=", self.item_group],
- ["Website Item Group", "item_group", "=", self.item_group] # consider website item groups
- ])
+ include_child = frappe.db.get_value("Item Group", self.item_group, "include_descendants")
+ if include_child:
+ include_groups = get_child_groups_for_website(self.item_group, include_self=True)
+ include_groups = [x.name for x in include_groups]
+ item_or_filters.extend([
+ ["item_group", "in", include_groups],
+ ["Website Item Group", "item_group", "=", self.item_group] # consider website item groups
+ ])
+ else:
+ item_or_filters.extend([
+ ["item_group", "=", self.item_group],
+ ["Website Item Group", "item_group", "=", self.item_group] # consider website item groups
+ ])
# Get link field values attached to published items
- item_filters['published_in_website'] = 1
item_values = frappe.get_all(
"Item",
fields=[df.fieldname],
diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py
index cfc3c7b..5c92e3d 100644
--- a/erpnext/e_commerce/product_data_engine/query.py
+++ b/erpnext/e_commerce/product_data_engine/query.py
@@ -46,10 +46,10 @@
self.filter_with_discount = bool(fields.get("discount"))
result, discount_list, website_item_groups, cart_items, count = [], [], [], [], 0
- website_item_groups = self.get_website_item_group_results(item_group, website_item_groups)
-
if fields:
self.build_fields_filters(fields)
+ if item_group:
+ self.build_item_group_filters(item_group)
if search_term:
self.build_search_filters(search_term)
if self.settings.hide_variants:
@@ -61,8 +61,6 @@
else:
result, count = self.query_items(start=start)
- result = self.combine_web_item_group_results(item_group, result, website_item_groups)
-
# sort combined results by ranking
result = sorted(result, key=lambda x: x.get("ranking"), reverse=True)
@@ -167,6 +165,25 @@
# `=` will be faster than `IN` for most cases
self.filters.append([field, "=", values])
+ def build_item_group_filters(self, item_group):
+ "Add filters for Item group page and include Website Item Groups."
+ from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website
+ item_group_filters = []
+
+ item_group_filters.append(["Website Item", "item_group", "=", item_group])
+ # Consider Website Item Groups
+ item_group_filters.append(["Website Item Group", "item_group", "=", item_group])
+
+ if frappe.db.get_value("Item Group", item_group, "include_descendants"):
+ # include child item group's items as well
+ # eg. Group Node A, will show items of child 1 and child 2 as well
+ # on it's web page
+ include_groups = get_child_groups_for_website(item_group, include_self=True)
+ include_groups = [x.name for x in include_groups]
+ item_group_filters.append(["Website Item", "item_group", "in", include_groups])
+
+ self.or_filters.extend(item_group_filters)
+
def build_search_filters(self, search_term):
"""Query search term in specified fields
@@ -190,19 +207,6 @@
for field in search_fields:
self.or_filters.append([field, "like", search])
- def get_website_item_group_results(self, item_group, website_item_groups):
- """Get Web Items for Item Group Page via Website Item Groups."""
- if item_group:
- website_item_groups = frappe.db.get_all(
- "Website Item",
- fields=self.fields + ["`tabWebsite Item Group`.parent as wig_parent"],
- filters=[
- ["Website Item Group", "item_group", "=", item_group],
- ["published", "=", 1]
- ]
- )
- return website_item_groups
-
def add_display_details(self, result, discount_list, cart_items):
"""Add price and availability details in result."""
for item in result:
@@ -278,16 +282,6 @@
return []
- def combine_web_item_group_results(self, item_group, result, website_item_groups):
- """Combine results with context of website item groups into item results."""
- if item_group and website_item_groups:
- items_list = {row.name for row in result}
- for row in website_item_groups:
- if row.wig_parent not in items_list:
- result.append(row)
-
- return result
-
def filter_results_by_discount(self, fields, result):
if fields and fields.get("discount"):
discount_percent = frappe.utils.flt(fields["discount"][0])
diff --git a/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py
index f0f7918..6549ba6 100644
--- a/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py
+++ b/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py
@@ -13,8 +13,7 @@
class TestItemGroupProductDataEngine(unittest.TestCase):
"Test Products & Sub-Category Querying for Product Listing on Item Group Page."
- @classmethod
- def setUpClass(cls):
+ def setUp(self):
item_codes = [
("Test Mobile A", "_Test Item Group B"),
("Test Mobile B", "_Test Item Group B"),
@@ -28,8 +27,10 @@
if not frappe.db.exists("Website Item", {"item_code": item_code}):
create_regular_web_item(item_code, item_args=item_args)
- @classmethod
- def tearDownClass(cls):
+ frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1)
+ frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 1)
+
+ def tearDown(self):
frappe.db.rollback()
def test_product_listing_in_item_group(self):
@@ -87,7 +88,6 @@
def test_item_group_with_sub_groups(self):
"Test Valid Sub Item Groups in Item Group Page."
- frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1)
frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 0)
result = get_product_filter_data(query_args={
@@ -114,4 +114,45 @@
# check if child group is fetched if shown in website
self.assertIn("_Test Item Group B - 1", child_groups)
- self.assertIn("_Test Item Group B - 2", child_groups)
\ No newline at end of file
+ self.assertIn("_Test Item Group B - 2", child_groups)
+
+ def test_item_group_page_with_descendants_included(self):
+ """
+ Test if 'include_descendants' pulls Items belonging to descendant Item Groups (Level 2 & 3).
+ > _Test Item Group B [Level 1]
+ > _Test Item Group B - 1 [Level 2]
+ > _Test Item Group B - 1 - 1 [Level 3]
+ """
+ frappe.get_doc({ # create Level 3 nested child group
+ "doctype": "Item Group",
+ "is_group": 1,
+ "item_group_name": "_Test Item Group B - 1 - 1",
+ "parent_item_group": "_Test Item Group B - 1"
+ }).insert()
+
+ create_regular_web_item( # create an item belonging to level 3 item group
+ "Test Mobile F",
+ item_args={"item_group": "_Test Item Group B - 1 - 1"}
+ )
+
+ frappe.db.set_value("Item Group", "_Test Item Group B - 1 - 1", "show_in_website", 1)
+
+ # enable 'include descendants' in Level 1
+ frappe.db.set_value("Item Group", "_Test Item Group B", "include_descendants", 1)
+
+ result = get_product_filter_data(query_args={
+ "field_filters": {},
+ "attribute_filters": {},
+ "start": 0,
+ "item_group": "_Test Item Group B"
+ })
+
+ items = result.get("items")
+ item_codes = [item.get("item_code") for item in items]
+
+ # check if all sub groups' items are pulled
+ self.assertEqual(len(items), 6)
+ self.assertIn("Test Mobile A", item_codes)
+ self.assertIn("Test Mobile C", item_codes)
+ self.assertIn("Test Mobile E", item_codes)
+ self.assertIn("Test Mobile F", item_codes)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index ef5f4bc..345d8dc 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -495,7 +495,6 @@
number_of_days = date_diff(to_date, from_date) + .5
else:
number_of_days = date_diff(to_date, from_date) + 1
-
else:
number_of_days = date_diff(to_date, from_date) + 1
diff --git a/erpnext/hr/report/monthly_attendance_sheet/test_monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/test_monthly_attendance_sheet.py
new file mode 100644
index 0000000..952af81
--- /dev/null
+++ b/erpnext/hr/report/monthly_attendance_sheet/test_monthly_attendance_sheet.py
@@ -0,0 +1,44 @@
+import frappe
+from dateutil.relativedelta import relativedelta
+from frappe.tests.utils import FrappeTestCase
+from frappe.utils import now_datetime
+
+from erpnext.hr.doctype.attendance.attendance import mark_attendance
+from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.report.monthly_attendance_sheet.monthly_attendance_sheet import execute
+
+
+class TestMonthlyAttendanceSheet(FrappeTestCase):
+ def setUp(self):
+ self.employee = make_employee("test_employee@example.com")
+ frappe.db.delete('Attendance', {'employee': self.employee})
+
+ def test_monthly_attendance_sheet_report(self):
+ now = now_datetime()
+ previous_month = now.month - 1
+ previous_month_first = now.replace(day=1).replace(month=previous_month).date()
+
+ company = frappe.db.get_value('Employee', self.employee, 'company')
+
+ # mark different attendance status on first 3 days of previous month
+ mark_attendance(self.employee, previous_month_first, 'Absent')
+ mark_attendance(self.employee, previous_month_first + relativedelta(days=1), 'Present')
+ mark_attendance(self.employee, previous_month_first + relativedelta(days=2), 'On Leave')
+
+ filters = frappe._dict({
+ 'month': previous_month,
+ 'year': now.year,
+ 'company': company,
+ })
+ report = execute(filters=filters)
+ employees = report[1][0]
+ datasets = report[3]['data']['datasets']
+ absent = datasets[0]['values']
+ present = datasets[1]['values']
+ leaves = datasets[2]['values']
+
+ # ensure correct attendance is reflect on the report
+ self.assertIn(self.employee, employees)
+ self.assertEqual(absent[0], 1)
+ self.assertEqual(present[1], 1)
+ self.assertEqual(leaves[2], 1)
diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
index b3ee340..7ae4c42 100644
--- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
+++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
@@ -5,10 +5,13 @@
frappe.reload_doc('accounts', 'doctype', 'bank', force=1)
if frappe.db.table_exists('Bank') and frappe.db.table_exists('Bank Account') and frappe.db.has_column('Bank Account', 'swift_number'):
- frappe.db.sql("""
- UPDATE `tabBank` b, `tabBank Account` ba
- SET b.swift_number = ba.swift_number WHERE b.name = ba.bank
- """)
+ try:
+ frappe.db.sql("""
+ UPDATE `tabBank` b, `tabBank Account` ba
+ SET b.swift_number = ba.swift_number WHERE b.name = ba.bank
+ """)
+ except Exception as e:
+ frappe.log_error(e, title="Patch Migration Failed")
frappe.reload_doc('accounts', 'doctype', 'bank_account')
frappe.reload_doc('accounts', 'doctype', 'payment_request')
diff --git a/erpnext/projects/report/project_profitability/project_profitability.py b/erpnext/projects/report/project_profitability/project_profitability.py
index 9520cd1..23c3b82 100644
--- a/erpnext/projects/report/project_profitability/project_profitability.py
+++ b/erpnext/projects/report/project_profitability/project_profitability.py
@@ -1,14 +1,12 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
-
import frappe
from frappe import _
from frappe.utils import flt
def execute(filters=None):
- columns, data = [], []
data = get_data(filters)
columns = get_columns()
charts = get_chart_data(data)
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index beac7ed..92a10c2 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -343,8 +343,7 @@
/* against number or, if empty, party against number */
%(temporary_against_account_number)s as 'Gegenkonto (ohne BU-Schlüssel)',
- /* disable automatic VAT deduction */
- '40' as 'BU-Schlüssel',
+ '' as 'BU-Schlüssel',
gl.posting_date as 'Belegdatum',
gl.voucher_no as 'Belegfeld 1',
diff --git a/erpnext/regional/report/irs_1099/irs_1099.py b/erpnext/regional/report/irs_1099/irs_1099.py
index b1a5d10..147a59f 100644
--- a/erpnext/regional/report/irs_1099/irs_1099.py
+++ b/erpnext/regional/report/irs_1099/irs_1099.py
@@ -30,7 +30,6 @@
if region != 'United States':
return [], []
- data = []
columns = get_columns()
conditions = ""
if filters.supplier_group:
diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
index 4133687..464939f 100644
--- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
+++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
@@ -118,8 +118,7 @@
"customer_type": "Company",
})
customer.insert()
- else:
- customer = frappe.get_doc("Customer", "_Test UAE Customer")
+
def make_supplier():
if not frappe.db.exists("Supplier", "_Test UAE Supplier"):
diff --git a/erpnext/setup/doctype/item_group/item_group.json b/erpnext/setup/doctype/item_group/item_group.json
index 3e0680f..50f923d 100644
--- a/erpnext/setup/doctype/item_group/item_group.json
+++ b/erpnext/setup/doctype/item_group/item_group.json
@@ -20,12 +20,14 @@
"sec_break_taxes",
"taxes",
"sb9",
- "show_in_website",
"route",
- "weightage",
- "slideshow",
"website_title",
"description",
+ "show_in_website",
+ "include_descendants",
+ "column_break_16",
+ "weightage",
+ "slideshow",
"website_specifications",
"website_filters_section",
"filter_fields",
@@ -111,7 +113,7 @@
},
{
"default": "0",
- "description": "Check this if you want to show in website",
+ "description": "Make Item Group visible in website",
"fieldname": "show_in_website",
"fieldtype": "Check",
"label": "Show in Website"
@@ -124,6 +126,7 @@
"unique": 1
},
{
+ "depends_on": "show_in_website",
"fieldname": "weightage",
"fieldtype": "Int",
"label": "Weightage"
@@ -186,6 +189,8 @@
"report_hide": 1
},
{
+ "collapsible": 1,
+ "depends_on": "show_in_website",
"fieldname": "website_filters_section",
"fieldtype": "Section Break",
"label": "Website Filters"
@@ -203,9 +208,22 @@
"options": "Website Attribute"
},
{
+ "depends_on": "show_in_website",
"fieldname": "website_title",
"fieldtype": "Data",
"label": "Title"
+ },
+ {
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "depends_on": "show_in_website",
+ "description": "Include Website Items belonging to child Item Groups",
+ "fieldname": "include_descendants",
+ "fieldtype": "Check",
+ "label": "Include Descendants"
}
],
"icon": "fa fa-sitemap",
@@ -214,11 +232,12 @@
"is_tree": 1,
"links": [],
"max_attachments": 3,
- "modified": "2021-02-18 13:40:30.049650",
+ "modified": "2022-03-09 12:27:11.055782",
"modified_by": "Administrator",
"module": "Setup",
"name": "Item Group",
"name_case": "Title Case",
+ "naming_rule": "By fieldname",
"nsm_parent_field": "parent_item_group",
"owner": "Administrator",
"permissions": [
@@ -285,5 +304,6 @@
"search_fields": "parent_item_group",
"show_name_in_global_search": 1,
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index 4f92240..5c7194b 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -111,7 +111,7 @@
from erpnext.stock.doctype.item.item import validate_item_default_company_links
validate_item_default_company_links(self.item_group_defaults)
-def get_child_groups_for_website(item_group_name, immediate=False):
+def get_child_groups_for_website(item_group_name, immediate=False, include_self=False):
"""Returns child item groups *excluding* passed group."""
item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
filters = {
@@ -123,6 +123,12 @@
if immediate:
filters["parent_item_group"] = item_group_name
+ if include_self:
+ filters.update({
+ "lft": [">=", item_group.lft],
+ "rgt": ["<=", item_group.rgt]
+ })
+
return frappe.get_all(
"Item Group",
filters=filters,
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 9bec5f7..9bb41b9 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -367,7 +367,7 @@
if not out[d[1]]:
out[d[1]] = frappe.get_cached_value('Company', args.company, d[2]) if d[2] else None
- for fieldname in ("item_name", "item_group", "barcodes", "brand", "stock_uom"):
+ for fieldname in ("item_name", "item_group", "brand", "stock_uom"):
out[fieldname] = item.get(fieldname)
if args.get("manufacturer"):
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index b4f43a7..24f47c1 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -18,7 +18,6 @@
is_reposting_item_valuation_in_progress()
if not filters: filters = {}
- from_date = filters.get('from_date')
to_date = filters.get('to_date')
if filters.get("company"):
diff --git a/erpnext/templates/pages/non_profit/__init__.py b/erpnext/templates/pages/non_profit/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/templates/pages/non_profit/__init__.py
diff --git a/erpnext/www/lms/macros/hero.html b/erpnext/www/lms/macros/hero.html
index 95ba8f7..dd3c23a 100644
--- a/erpnext/www/lms/macros/hero.html
+++ b/erpnext/www/lms/macros/hero.html
@@ -39,16 +39,13 @@
frappe.call(opts).then(res => {
let success_dialog = new frappe.ui.Dialog({
title: __('Success'),
- primary_action_label: __('View Program Content'),
+ primary_action_label: __('OK'),
primary_action: function() {
window.location.reload();
- },
- secondary_action: function() {
- window.location.reload();
}
})
success_dialog.show();
- success_dialog.set_message(__('You have successfully enrolled for the program '));
+ success_dialog.set_message(__('You have successfully enrolled for the program.'));
})
}
</script>