From 0c0a9ed96d3b11741cf506c95f9e5e16fcdcfe68 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Wed, 5 Jan 2022 09:17:46 +0530
Subject: [PATCH 01/64] refactor: Remove non-profit domain from ERPNext
---
erpnext/domains/non_profit.py | 22 -
erpnext/hooks.py | 16 -
erpnext/modules.txt | 1 -
erpnext/non_profit/__init__.py | 0
erpnext/non_profit/doctype/__init__.py | 0
.../certification_application/__init__.py | 0
.../certification_application.js | 8 -
.../certification_application.json | 323 -------
.../certification_application.py | 9 -
.../test_certification_application.py | 8 -
.../doctype/certified_consultant/__init__.py | 0
.../certified_consultant.js | 8 -
.../certified_consultant.json | 724 ---------------
.../certified_consultant.py | 9 -
.../test_certified_consultant.py | 8 -
.../non_profit/doctype/chapter/__init__.py | 0
erpnext/non_profit/doctype/chapter/chapter.js | 8 -
.../non_profit/doctype/chapter/chapter.json | 397 --------
erpnext/non_profit/doctype/chapter/chapter.py | 49 -
.../doctype/chapter/templates/chapter.html | 79 --
.../chapter/templates/chapter_row.html | 25 -
.../doctype/chapter/test_chapter.py | 8 -
.../doctype/chapter_member/__init__.py | 0
.../chapter_member/chapter_member.json | 199 ----
.../doctype/chapter_member/chapter_member.py | 9 -
.../non_profit/doctype/donation/__init__.py | 0
.../non_profit/doctype/donation/donation.js | 26 -
.../non_profit/doctype/donation/donation.json | 156 ----
.../non_profit/doctype/donation/donation.py | 220 -----
.../doctype/donation/donation_dashboard.py | 16 -
.../doctype/donation/test_donation.py | 77 --
erpnext/non_profit/doctype/donor/__init__.py | 0
erpnext/non_profit/doctype/donor/donor.js | 17 -
erpnext/non_profit/doctype/donor/donor.json | 110 ---
erpnext/non_profit/doctype/donor/donor.py | 17 -
.../non_profit/doctype/donor/donor_list.js | 3 -
.../non_profit/doctype/donor/test_donor.py | 8 -
.../non_profit/doctype/donor_type/__init__.py | 0
.../doctype/donor_type/donor_type.js | 8 -
.../doctype/donor_type/donor_type.json | 94 --
.../doctype/donor_type/donor_type.py | 9 -
.../doctype/donor_type/test_donor_type.py | 8 -
.../doctype/grant_application/__init__.py | 0
.../grant_application/grant_application.js | 27 -
.../grant_application/grant_application.json | 851 ------------------
.../grant_application/grant_application.py | 58 --
.../templates/grant_application.html | 68 --
.../templates/grant_application_row.html | 11 -
.../test_grant_application.py | 8 -
erpnext/non_profit/doctype/member/__init__.py | 0
erpnext/non_profit/doctype/member/member.js | 64 --
erpnext/non_profit/doctype/member/member.json | 210 -----
erpnext/non_profit/doctype/member/member.py | 185 ----
.../doctype/member/member_dashboard.py | 22 -
.../non_profit/doctype/member/member_list.js | 3 -
.../non_profit/doctype/member/test_member.py | 8 -
.../non_profit/doctype/membership/__init__.py | 0
.../doctype/membership/membership.js | 41 -
.../doctype/membership/membership.json | 184 ----
.../doctype/membership/membership_list.js | 15 -
.../doctype/membership/test_membership.py | 164 ----
.../doctype/membership_type/__init__.py | 0
.../membership_type/membership_type.js | 22 -
.../membership_type/membership_type.json | 71 --
.../membership_type/membership_type.py | 18 -
.../membership_type/test_membership_type.py | 8 -
.../doctype/non_profit_settings/__init__.py | 0
.../non_profit_settings.js | 133 ---
.../non_profit_settings.json | 273 ------
.../non_profit_settings.py | 38 -
.../test_non_profit_settings.py | 9 -
.../non_profit/doctype/volunteer/__init__.py | 0
.../doctype/volunteer/test_volunteer.py | 8 -
.../non_profit/doctype/volunteer/volunteer.js | 17 -
.../doctype/volunteer/volunteer.json | 148 ---
.../non_profit/doctype/volunteer/volunteer.py | 12 -
.../doctype/volunteer_skill/__init__.py | 0
.../volunteer_skill/volunteer_skill.json | 73 --
.../volunteer_skill/volunteer_skill.py | 9 -
.../doctype/volunteer_type/__init__.py | 0
.../volunteer_type/test_volunteer_type.py | 8 -
.../doctype/volunteer_type/volunteer_type.js | 8 -
.../volunteer_type/volunteer_type.json | 94 --
.../doctype/volunteer_type/volunteer_type.py | 9 -
erpnext/non_profit/report/__init__.py | 0
.../report/expiring_memberships/__init__.py | 0
.../expiring_memberships.js | 24 -
.../expiring_memberships.json | 27 -
.../expiring_memberships.py | 34 -
erpnext/non_profit/utils.py | 12 -
erpnext/non_profit/web_form/__init__.py | 0
.../certification_application/__init__.py | 0
.../certification_application.js | 16 -
.../certification_application.json | 79 --
.../certification_application.py | 3 -
.../certification_application_usd/__init__.py | 0
.../certification_application_usd.js | 16 -
.../certification_application_usd.json | 80 --
.../certification_application_usd.py | 3 -
.../web_form/grant_application/__init__.py | 0
.../grant_application/grant_application.js | 3 -
.../grant_application/grant_application.json | 108 ---
.../grant_application/grant_application.py | 4 -
.../workspace/non_profit/non_profit.json | 272 ------
erpnext/patches.txt | 2 +
.../v13_0/non_profit_deprecation_warning.py | 10 +
.../v14_0/delete_non_profit_doctypes.py | 19 +
erpnext/regional/india/setup.py | 8 -
.../operations/install_fixtures.py | 1 -
109 files changed, 31 insertions(+), 6246 deletions(-)
delete mode 100644 erpnext/domains/non_profit.py
delete mode 100644 erpnext/non_profit/__init__.py
delete mode 100644 erpnext/non_profit/doctype/__init__.py
delete mode 100644 erpnext/non_profit/doctype/certification_application/__init__.py
delete mode 100644 erpnext/non_profit/doctype/certification_application/certification_application.js
delete mode 100644 erpnext/non_profit/doctype/certification_application/certification_application.json
delete mode 100644 erpnext/non_profit/doctype/certification_application/certification_application.py
delete mode 100644 erpnext/non_profit/doctype/certification_application/test_certification_application.py
delete mode 100644 erpnext/non_profit/doctype/certified_consultant/__init__.py
delete mode 100644 erpnext/non_profit/doctype/certified_consultant/certified_consultant.js
delete mode 100644 erpnext/non_profit/doctype/certified_consultant/certified_consultant.json
delete mode 100644 erpnext/non_profit/doctype/certified_consultant/certified_consultant.py
delete mode 100644 erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py
delete mode 100644 erpnext/non_profit/doctype/chapter/__init__.py
delete mode 100644 erpnext/non_profit/doctype/chapter/chapter.js
delete mode 100644 erpnext/non_profit/doctype/chapter/chapter.json
delete mode 100644 erpnext/non_profit/doctype/chapter/chapter.py
delete mode 100644 erpnext/non_profit/doctype/chapter/templates/chapter.html
delete mode 100644 erpnext/non_profit/doctype/chapter/templates/chapter_row.html
delete mode 100644 erpnext/non_profit/doctype/chapter/test_chapter.py
delete mode 100644 erpnext/non_profit/doctype/chapter_member/__init__.py
delete mode 100644 erpnext/non_profit/doctype/chapter_member/chapter_member.json
delete mode 100644 erpnext/non_profit/doctype/chapter_member/chapter_member.py
delete mode 100644 erpnext/non_profit/doctype/donation/__init__.py
delete mode 100644 erpnext/non_profit/doctype/donation/donation.js
delete mode 100644 erpnext/non_profit/doctype/donation/donation.json
delete mode 100644 erpnext/non_profit/doctype/donation/donation.py
delete mode 100644 erpnext/non_profit/doctype/donation/donation_dashboard.py
delete mode 100644 erpnext/non_profit/doctype/donation/test_donation.py
delete mode 100644 erpnext/non_profit/doctype/donor/__init__.py
delete mode 100644 erpnext/non_profit/doctype/donor/donor.js
delete mode 100644 erpnext/non_profit/doctype/donor/donor.json
delete mode 100644 erpnext/non_profit/doctype/donor/donor.py
delete mode 100644 erpnext/non_profit/doctype/donor/donor_list.js
delete mode 100644 erpnext/non_profit/doctype/donor/test_donor.py
delete mode 100644 erpnext/non_profit/doctype/donor_type/__init__.py
delete mode 100644 erpnext/non_profit/doctype/donor_type/donor_type.js
delete mode 100644 erpnext/non_profit/doctype/donor_type/donor_type.json
delete mode 100644 erpnext/non_profit/doctype/donor_type/donor_type.py
delete mode 100644 erpnext/non_profit/doctype/donor_type/test_donor_type.py
delete mode 100644 erpnext/non_profit/doctype/grant_application/__init__.py
delete mode 100644 erpnext/non_profit/doctype/grant_application/grant_application.js
delete mode 100644 erpnext/non_profit/doctype/grant_application/grant_application.json
delete mode 100644 erpnext/non_profit/doctype/grant_application/grant_application.py
delete mode 100644 erpnext/non_profit/doctype/grant_application/templates/grant_application.html
delete mode 100644 erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html
delete mode 100644 erpnext/non_profit/doctype/grant_application/test_grant_application.py
delete mode 100644 erpnext/non_profit/doctype/member/__init__.py
delete mode 100644 erpnext/non_profit/doctype/member/member.js
delete mode 100644 erpnext/non_profit/doctype/member/member.json
delete mode 100644 erpnext/non_profit/doctype/member/member.py
delete mode 100644 erpnext/non_profit/doctype/member/member_dashboard.py
delete mode 100644 erpnext/non_profit/doctype/member/member_list.js
delete mode 100644 erpnext/non_profit/doctype/member/test_member.py
delete mode 100644 erpnext/non_profit/doctype/membership/__init__.py
delete mode 100644 erpnext/non_profit/doctype/membership/membership.js
delete mode 100644 erpnext/non_profit/doctype/membership/membership.json
delete mode 100644 erpnext/non_profit/doctype/membership/membership_list.js
delete mode 100644 erpnext/non_profit/doctype/membership/test_membership.py
delete mode 100644 erpnext/non_profit/doctype/membership_type/__init__.py
delete mode 100644 erpnext/non_profit/doctype/membership_type/membership_type.js
delete mode 100644 erpnext/non_profit/doctype/membership_type/membership_type.json
delete mode 100644 erpnext/non_profit/doctype/membership_type/membership_type.py
delete mode 100644 erpnext/non_profit/doctype/membership_type/test_membership_type.py
delete mode 100644 erpnext/non_profit/doctype/non_profit_settings/__init__.py
delete mode 100644 erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js
delete mode 100644 erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json
delete mode 100644 erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py
delete mode 100644 erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
delete mode 100644 erpnext/non_profit/doctype/volunteer/__init__.py
delete mode 100644 erpnext/non_profit/doctype/volunteer/test_volunteer.py
delete mode 100644 erpnext/non_profit/doctype/volunteer/volunteer.js
delete mode 100644 erpnext/non_profit/doctype/volunteer/volunteer.json
delete mode 100644 erpnext/non_profit/doctype/volunteer/volunteer.py
delete mode 100644 erpnext/non_profit/doctype/volunteer_skill/__init__.py
delete mode 100644 erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json
delete mode 100644 erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py
delete mode 100644 erpnext/non_profit/doctype/volunteer_type/__init__.py
delete mode 100644 erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py
delete mode 100644 erpnext/non_profit/doctype/volunteer_type/volunteer_type.js
delete mode 100644 erpnext/non_profit/doctype/volunteer_type/volunteer_type.json
delete mode 100644 erpnext/non_profit/doctype/volunteer_type/volunteer_type.py
delete mode 100644 erpnext/non_profit/report/__init__.py
delete mode 100644 erpnext/non_profit/report/expiring_memberships/__init__.py
delete mode 100644 erpnext/non_profit/report/expiring_memberships/expiring_memberships.js
delete mode 100644 erpnext/non_profit/report/expiring_memberships/expiring_memberships.json
delete mode 100644 erpnext/non_profit/report/expiring_memberships/expiring_memberships.py
delete mode 100644 erpnext/non_profit/utils.py
delete mode 100644 erpnext/non_profit/web_form/__init__.py
delete mode 100644 erpnext/non_profit/web_form/certification_application/__init__.py
delete mode 100644 erpnext/non_profit/web_form/certification_application/certification_application.js
delete mode 100644 erpnext/non_profit/web_form/certification_application/certification_application.json
delete mode 100644 erpnext/non_profit/web_form/certification_application/certification_application.py
delete mode 100644 erpnext/non_profit/web_form/certification_application_usd/__init__.py
delete mode 100644 erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js
delete mode 100644 erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json
delete mode 100644 erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py
delete mode 100644 erpnext/non_profit/web_form/grant_application/__init__.py
delete mode 100644 erpnext/non_profit/web_form/grant_application/grant_application.js
delete mode 100644 erpnext/non_profit/web_form/grant_application/grant_application.json
delete mode 100644 erpnext/non_profit/web_form/grant_application/grant_application.py
delete mode 100644 erpnext/non_profit/workspace/non_profit/non_profit.json
create mode 100644 erpnext/patches/v13_0/non_profit_deprecation_warning.py
create mode 100644 erpnext/patches/v14_0/delete_non_profit_doctypes.py
diff --git a/erpnext/domains/non_profit.py b/erpnext/domains/non_profit.py
deleted file mode 100644
index d9fc5e5df0..0000000000
--- a/erpnext/domains/non_profit.py
+++ /dev/null
@@ -1,22 +0,0 @@
-data = {
- 'desktop_icons': [
- 'Non Profit',
- 'Member',
- 'Donor',
- 'Volunteer',
- 'Grant Application',
- 'Accounts',
- 'Buying',
- 'HR',
- 'ToDo'
- ],
- 'restricted_roles': [
- 'Non Profit Manager',
- 'Non Profit Member',
- 'Non Profit Portal User'
- ],
- 'modules': [
- 'Non Profit'
- ],
- 'default_portal_role': 'Non Profit Manager'
-}
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index f014b0e1e9..4502f2b97b 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -69,7 +69,6 @@ domains = {
'Education': 'erpnext.domains.education',
'Hospitality': 'erpnext.domains.hospitality',
'Manufacturing': 'erpnext.domains.manufacturing',
- 'Non Profit': 'erpnext.domains.non_profit',
'Retail': 'erpnext.domains.retail',
'Services': 'erpnext.domains.services',
}
@@ -176,7 +175,6 @@ standard_portal_menu_items = [
{"title": _("Fees"), "route": "/fees", "reference_doctype": "Fees", "role":"Student"},
{"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"},
{"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission", "role": "Student"},
- {"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application", "role": "Non Profit Portal User"},
{"title": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"},
{"title": _("Appointment Booking"), "route": "/book_appointment"},
]
@@ -373,7 +371,6 @@ scheduler_events = {
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email",
- "erpnext.non_profit.doctype.membership.membership.set_expired_status",
"erpnext.hr.doctype.interview.interview.send_daily_feedback_reminder"
],
"daily_long": [
@@ -566,19 +563,6 @@ global_search_doctypes = {
{'doctype': 'Assessment Code', 'index': 39},
{'doctype': 'Discussion', 'index': 40},
],
- "Non Profit": [
- {'doctype': 'Certified Consultant', 'index': 1},
- {'doctype': 'Certification Application', 'index': 2},
- {'doctype': 'Volunteer', 'index': 3},
- {'doctype': 'Membership', 'index': 4},
- {'doctype': 'Member', 'index': 5},
- {'doctype': 'Donor', 'index': 6},
- {'doctype': 'Chapter', 'index': 7},
- {'doctype': 'Grant Application', 'index': 8},
- {'doctype': 'Volunteer Type', 'index': 9},
- {'doctype': 'Donor Type', 'index': 10},
- {'doctype': 'Membership Type', 'index': 11}
- ],
"Hospitality": [
{'doctype': 'Hotel Room', 'index': 0},
{'doctype': 'Hotel Room Reservation', 'index': 1},
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index ae0bb2d5c9..cd1586c290 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -17,7 +17,6 @@ Education
Regional
Restaurant
ERPNext Integrations
-Non Profit
Hotels
Quality Management
Communication
diff --git a/erpnext/non_profit/__init__.py b/erpnext/non_profit/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/__init__.py b/erpnext/non_profit/doctype/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/certification_application/__init__.py b/erpnext/non_profit/doctype/certification_application/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.js b/erpnext/non_profit/doctype/certification_application/certification_application.js
deleted file mode 100644
index 1e6a9a4b01..0000000000
--- a/erpnext/non_profit/doctype/certification_application/certification_application.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Certification Application', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.json b/erpnext/non_profit/doctype/certification_application/certification_application.json
deleted file mode 100644
index f562fa6734..0000000000
--- a/erpnext/non_profit/doctype/certification_application/certification_application.json
+++ /dev/null
@@ -1,323 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "NPO-CAPP-.YYYY.-.#####",
- "beta": 0,
- "creation": "2018-06-08 16:12:42.091729",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "name_of_applicant",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Name of Applicant",
- "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": "email",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Email",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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": "column_break_1",
- "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_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "certification_status",
- "fieldtype": "Select",
- "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": "Certification Status",
- "length": 0,
- "no_copy": 0,
- "options": "Yet to appear\nCertified\nNot Certified",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "payment_details",
- "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,
- "label": "Payment Details",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "paid",
- "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": "Paid",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "currency",
- "fieldtype": "Select",
- "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": "Currency",
- "length": 0,
- "no_copy": 0,
- "options": "USD\nINR",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Float",
- "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": "Amount",
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-04 03:36:35.337403",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Certification Application",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.py b/erpnext/non_profit/doctype/certification_application/certification_application.py
deleted file mode 100644
index cbbe191fba..0000000000
--- a/erpnext/non_profit/doctype/certification_application/certification_application.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class CertificationApplication(Document):
- pass
diff --git a/erpnext/non_profit/doctype/certification_application/test_certification_application.py b/erpnext/non_profit/doctype/certification_application/test_certification_application.py
deleted file mode 100644
index 8687b4daf4..0000000000
--- a/erpnext/non_profit/doctype/certification_application/test_certification_application.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestCertificationApplication(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/certified_consultant/__init__.py b/erpnext/non_profit/doctype/certified_consultant/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js
deleted file mode 100644
index cd004c3489..0000000000
--- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Certified Consultant', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json
deleted file mode 100644
index d77f1b2569..0000000000
--- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json
+++ /dev/null
@@ -1,724 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "NPO-CONS-.YYYY.-.#####",
- "beta": 0,
- "creation": "2018-06-13 17:27:19.838334",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "name_of_consultant",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Name of Consultant",
- "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": "country",
- "fieldtype": "Link",
- "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": "Country",
- "length": 0,
- "no_copy": 0,
- "options": "Country",
- "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": "email",
- "fieldtype": "Link",
- "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": "Email",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "phone",
- "fieldtype": "Data",
- "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": "Phone",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "website_url",
- "fieldtype": "Data",
- "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": "Website",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address",
- "fieldtype": "Small Text",
- "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": "Address",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break1",
- "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_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "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": "Image",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "certification_application",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Certification Application",
- "length": 0,
- "no_copy": 0,
- "options": "Certification Application",
- "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": "section_break1",
- "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,
- "label": "Certification Validity",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_beak2",
- "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_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",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break2",
- "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,
- "label": "",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "introduction",
- "fieldtype": "Small Text",
- "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": "Introduction",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "details",
- "fieldtype": "Text Editor",
- "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": "Details",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break3",
- "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_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "discuss_id",
- "fieldtype": "Data",
- "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": "Discuss ID",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "github_id",
- "fieldtype": "Data",
- "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": "GitHub ID",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "show_in_website",
- "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": "Show in Website",
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-04 03:36:47.386618",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Certified Consultant",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py
deleted file mode 100644
index 47361cc39e..0000000000
--- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class CertifiedConsultant(Document):
- pass
diff --git a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py
deleted file mode 100644
index d10353c1e4..0000000000
--- a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestCertifiedConsultant(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/chapter/__init__.py b/erpnext/non_profit/doctype/chapter/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/chapter/chapter.js b/erpnext/non_profit/doctype/chapter/chapter.js
deleted file mode 100644
index c8b6d4a644..0000000000
--- a/erpnext/non_profit/doctype/chapter/chapter.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Chapter', {
- refresh: function() {
-
- }
-});
diff --git a/erpnext/non_profit/doctype/chapter/chapter.json b/erpnext/non_profit/doctype/chapter/chapter.json
deleted file mode 100644
index 86cba9a178..0000000000
--- a/erpnext/non_profit/doctype/chapter/chapter.json
+++ /dev/null
@@ -1,397 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 1,
- "allow_import": 0,
- "allow_rename": 1,
- "autoname": "prompt",
- "beta": 0,
- "creation": "2017-09-14 13:36:03.904702",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "chapter_head",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Chapter Head",
- "length": 0,
- "no_copy": 0,
- "options": "Member",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_3",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "region",
- "fieldtype": "Data",
- "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": "Region",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_5",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "introduction",
- "fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Introduction",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "meetup_embed_html",
- "fieldtype": "Code",
- "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": "Meetup Embed HTML",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address",
- "fieldtype": "Text",
- "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": "Address",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "chapters/chapter_name\nleave blank automatically set after saving chapter.",
- "fieldname": "route",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Route",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "published",
- "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": "Published",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "chapter_members",
- "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,
- "label": "Chapter Members",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "members",
- "fieldtype": "Table",
- "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": "Members",
- "length": 0,
- "no_copy": 0,
- "options": "Chapter Member",
- "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,
- "unique": 0
- }
- ],
- "has_web_view": 1,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_published_field": "published",
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-12-14 12:59:31.424240",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Chapter",
- "name_case": "Title Case",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "route": "chapters",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/chapter/chapter.py b/erpnext/non_profit/doctype/chapter/chapter.py
deleted file mode 100644
index c01b1ef3e4..0000000000
--- a/erpnext/non_profit/doctype/chapter/chapter.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.website.website_generator import WebsiteGenerator
-
-
-class Chapter(WebsiteGenerator):
- _website = frappe._dict(
- condition_field = "published",
- )
-
- def get_context(self, context):
- context.no_cache = True
- context.show_sidebar = True
- context.parents = [dict(label='View All Chapters',
- route='chapters', title='View Chapters')]
-
- def validate(self):
- if not self.route: #pylint: disable=E0203
- self.route = 'chapters/' + self.scrub(self.name)
-
- def enable(self):
- chapter = frappe.get_doc('Chapter', frappe.form_dict.name)
- chapter.append('members', dict(enable=self.value))
- chapter.save(ignore_permissions=1)
- frappe.db.commit()
-
-
-def get_list_context(context):
- context.allow_guest = True
- context.no_cache = True
- context.show_sidebar = True
- context.title = 'All Chapters'
- context.no_breadcrumbs = True
- context.order_by = 'creation desc'
-
-
-@frappe.whitelist()
-def leave(title, user_id, leave_reason):
- chapter = frappe.get_doc("Chapter", title)
- for member in chapter.members:
- if member.user == user_id:
- member.enabled = 0
- member.leave_reason = leave_reason
- chapter.save(ignore_permissions=1)
- frappe.db.commit()
- return "Thank you for Feedback"
diff --git a/erpnext/non_profit/doctype/chapter/templates/chapter.html b/erpnext/non_profit/doctype/chapter/templates/chapter.html
deleted file mode 100644
index 321828f73f..0000000000
--- a/erpnext/non_profit/doctype/chapter/templates/chapter.html
+++ /dev/null
@@ -1,79 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
-{{ title }}
-{{ introduction }}
-{% if meetup_embed_html %}
- {{ meetup_embed_html }}
-{% endif %}
-Member Details
-
-{% if members %}
-
- {% set index = [1] %}
- {% for user in members %}
- {% if user.enabled == 1 %}
-
-
-
-
-
-
- {{ index|length }}. {{ frappe.db.get_value('User', user.user, 'full_name') }}
-
-
-
-
-
-
- {% if user.introduction %}
- {{ user.introduction }}
- {% endif %}
-
-
-
-
-
- {% set __ = index.append(1) %}
- {% endif %}
- {% endfor %}
-
-{% else %}
- No member yet.
-{% endif %}
-
-Chapter Head
-
-
-
- {% set doc = frappe.get_doc('Member',chapter_head) %}
-
- Name
- {{ doc.member_name }}
-
-
- Email
- {{ frappe.db.get_value('User', doc.email, 'email') or '' }}
-
-
- Phone
- {{ frappe.db.get_value('User', doc.email, 'phone') or '' }}
-
-
-
-
-{% if address %}
-Address
-
-{% endif %}
-
-Join this Chapter
-Leave this Chapter
-
-{% endblock %}
diff --git a/erpnext/non_profit/doctype/chapter/templates/chapter_row.html b/erpnext/non_profit/doctype/chapter/templates/chapter_row.html
deleted file mode 100644
index cad34fa5be..0000000000
--- a/erpnext/non_profit/doctype/chapter/templates/chapter_row.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% if doc.published %}
-
-{% endif %}
diff --git a/erpnext/non_profit/doctype/chapter/test_chapter.py b/erpnext/non_profit/doctype/chapter/test_chapter.py
deleted file mode 100644
index 98601efcf2..0000000000
--- a/erpnext/non_profit/doctype/chapter/test_chapter.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestChapter(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/chapter_member/__init__.py b/erpnext/non_profit/doctype/chapter_member/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/chapter_member/chapter_member.json b/erpnext/non_profit/doctype/chapter_member/chapter_member.json
deleted file mode 100644
index 478bfd9331..0000000000
--- a/erpnext/non_profit/doctype/chapter_member/chapter_member.json
+++ /dev/null
@@ -1,199 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-09-14 13:38:04.296375",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "user",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "User",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "introduction",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Introduction",
- "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": "website_url",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Website URL",
- "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": 2,
- "default": "1",
- "fieldname": "enabled",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Enabled",
- "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": "leave_reason",
- "fieldtype": "Data",
- "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": "Leave Reason",
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-03-07 05:36:51.664816",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Chapter Member",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/chapter_member/chapter_member.py b/erpnext/non_profit/doctype/chapter_member/chapter_member.py
deleted file mode 100644
index 80c0446ee5..0000000000
--- a/erpnext/non_profit/doctype/chapter_member/chapter_member.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class ChapterMember(Document):
- pass
diff --git a/erpnext/non_profit/doctype/donation/__init__.py b/erpnext/non_profit/doctype/donation/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/donation/donation.js b/erpnext/non_profit/doctype/donation/donation.js
deleted file mode 100644
index 10e8220144..0000000000
--- a/erpnext/non_profit/doctype/donation/donation.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Donation', {
- refresh: function(frm) {
- if (frm.doc.docstatus === 1 && !frm.doc.paid) {
- frm.add_custom_button(__('Create Payment Entry'), function() {
- frm.events.make_payment_entry(frm);
- });
- }
- },
-
- make_payment_entry: function(frm) {
- return frappe.call({
- method: 'erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry',
- args: {
- 'dt': frm.doc.doctype,
- 'dn': frm.doc.name
- },
- callback: function(r) {
- var doc = frappe.model.sync(r.message);
- frappe.set_route('Form', doc[0].doctype, doc[0].name);
- }
- });
- },
-});
diff --git a/erpnext/non_profit/doctype/donation/donation.json b/erpnext/non_profit/doctype/donation/donation.json
deleted file mode 100644
index 6759569d54..0000000000
--- a/erpnext/non_profit/doctype/donation/donation.json
+++ /dev/null
@@ -1,156 +0,0 @@
-{
- "actions": [],
- "autoname": "naming_series:",
- "creation": "2021-02-17 10:28:52.645731",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "naming_series",
- "donor",
- "donor_name",
- "email",
- "column_break_4",
- "company",
- "date",
- "payment_details_section",
- "paid",
- "amount",
- "mode_of_payment",
- "razorpay_payment_id",
- "amended_from"
- ],
- "fields": [
- {
- "fieldname": "donor",
- "fieldtype": "Link",
- "label": "Donor",
- "options": "Donor",
- "reqd": 1
- },
- {
- "fetch_from": "donor.donor_name",
- "fieldname": "donor_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Donor Name",
- "read_only": 1
- },
- {
- "fetch_from": "donor.email",
- "fieldname": "email",
- "fieldtype": "Data",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Email",
- "read_only": 1
- },
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "date",
- "fieldtype": "Date",
- "label": "Date",
- "reqd": 1
- },
- {
- "fieldname": "payment_details_section",
- "fieldtype": "Section Break",
- "label": "Payment Details"
- },
- {
- "fieldname": "amount",
- "fieldtype": "Currency",
- "label": "Amount",
- "reqd": 1
- },
- {
- "fieldname": "mode_of_payment",
- "fieldtype": "Link",
- "label": "Mode of Payment",
- "options": "Mode of Payment"
- },
- {
- "fieldname": "razorpay_payment_id",
- "fieldtype": "Data",
- "label": "Razorpay Payment ID",
- "read_only": 1
- },
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Naming Series",
- "options": "NPO-DTN-.YYYY.-"
- },
- {
- "default": "0",
- "fieldname": "paid",
- "fieldtype": "Check",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Paid"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "label": "Amended From",
- "no_copy": 1,
- "options": "Donation",
- "print_hide": 1,
- "read_only": 1
- }
- ],
- "index_web_pages_for_search": 1,
- "is_submittable": 1,
- "links": [],
- "modified": "2021-03-11 10:53:11.269005",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Donation",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "select": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "select": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- }
- ],
- "search_fields": "donor_name, email",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "donor_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donation/donation.py b/erpnext/non_profit/doctype/donation/donation.py
deleted file mode 100644
index 54bc94b755..0000000000
--- a/erpnext/non_profit/doctype/donation/donation.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import json
-
-import frappe
-from frappe import _
-from frappe.email import sendmail_to_system_managers
-from frappe.model.document import Document
-from frappe.utils import flt, get_link_to_form, getdate
-
-from erpnext.non_profit.doctype.membership.membership import verify_signature
-
-
-class Donation(Document):
- def validate(self):
- if not self.donor or not frappe.db.exists('Donor', self.donor):
- # for web forms
- user_type = frappe.db.get_value('User', frappe.session.user, 'user_type')
- if user_type == 'Website User':
- self.create_donor_for_website_user()
- else:
- frappe.throw(_('Please select a Member'))
-
- def create_donor_for_website_user(self):
- donor_name = frappe.get_value('Donor', dict(email=frappe.session.user))
-
- if not donor_name:
- user = frappe.get_doc('User', frappe.session.user)
- donor = frappe.get_doc(dict(
- doctype='Donor',
- donor_type=self.get('donor_type'),
- email=frappe.session.user,
- member_name=user.get_fullname()
- )).insert(ignore_permissions=True)
- donor_name = donor.name
-
- if self.get('__islocal'):
- self.donor = donor_name
-
- def on_payment_authorized(self, *args, **kwargs):
- self.load_from_db()
- self.create_payment_entry()
-
- def create_payment_entry(self, date=None):
- settings = frappe.get_doc('Non Profit Settings')
- if not settings.automate_donation_payment_entries:
- return
-
- if not settings.donation_payment_account:
- frappe.throw(_('You need to set Payment Account for Donation in {0}').format(
- get_link_to_form('Non Profit Settings', 'Non Profit Settings')))
-
- from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
-
- frappe.flags.ignore_account_permission = True
- pe = get_payment_entry(dt=self.doctype, dn=self.name)
- frappe.flags.ignore_account_permission = False
- pe.paid_from = settings.donation_debit_account
- pe.paid_to = settings.donation_payment_account
- pe.posting_date = date or getdate()
- pe.reference_no = self.name
- pe.reference_date = date or getdate()
- pe.flags.ignore_mandatory = True
- pe.insert()
- pe.submit()
-
-
-@frappe.whitelist(allow_guest=True)
-def capture_razorpay_donations(*args, **kwargs):
- """
- Creates Donation from Razorpay Webhook Request Data on payment.captured event
- Creates Donor from email if not found
- """
- data = frappe.request.get_data(as_text=True)
-
- try:
- verify_signature(data, endpoint='Donation')
- except Exception as e:
- log = frappe.log_error(e, 'Donation Webhook Verification Error')
- notify_failure(log)
- return { 'status': 'Failed', 'reason': e }
-
- if isinstance(data, str):
- data = json.loads(data)
- data = frappe._dict(data)
-
- payment = data.payload.get('payment', {}).get('entity', {})
- payment = frappe._dict(payment)
-
- try:
- if not data.event == 'payment.captured':
- return
-
- # to avoid capturing subscription payments as donations
- if payment.description and 'subscription' in str(payment.description).lower():
- return
-
- donor = get_donor(payment.email)
- if not donor:
- donor = create_donor(payment)
-
- donation = create_donation(donor, payment)
- donation.run_method('create_payment_entry')
-
- except Exception as e:
- message = '{0}\n\n{1}\n\n{2}: {3}'.format(e, frappe.get_traceback(), _('Payment ID'), payment.id)
- log = frappe.log_error(message, _('Error creating donation entry for {0}').format(donor.name))
- notify_failure(log)
- return { 'status': 'Failed', 'reason': e }
-
- return { 'status': 'Success' }
-
-
-def create_donation(donor, payment):
- if not frappe.db.exists('Mode of Payment', payment.method):
- create_mode_of_payment(payment.method)
-
- company = get_company_for_donations()
- donation = frappe.get_doc({
- 'doctype': 'Donation',
- 'company': company,
- 'donor': donor.name,
- 'donor_name': donor.donor_name,
- 'email': donor.email,
- 'date': getdate(),
- 'amount': flt(payment.amount) / 100, # Convert to rupees from paise
- 'mode_of_payment': payment.method,
- 'razorpay_payment_id': payment.id
- }).insert(ignore_mandatory=True)
-
- donation.submit()
- return donation
-
-
-def get_donor(email):
- donors = frappe.get_all('Donor',
- filters={'email': email},
- order_by='creation desc')
-
- try:
- return frappe.get_doc('Donor', donors[0]['name'])
- except Exception:
- return None
-
-
-@frappe.whitelist()
-def create_donor(payment):
- donor_details = frappe._dict(payment)
- donor_type = frappe.db.get_single_value('Non Profit Settings', 'default_donor_type')
-
- donor = frappe.new_doc('Donor')
- donor.update({
- 'donor_name': donor_details.email,
- 'donor_type': donor_type,
- 'email': donor_details.email,
- 'contact': donor_details.contact
- })
-
- if donor_details.get('notes'):
- donor = get_additional_notes(donor, donor_details)
-
- donor.insert(ignore_mandatory=True)
- return donor
-
-
-def get_company_for_donations():
- company = frappe.db.get_single_value('Non Profit Settings', 'donation_company')
- if not company:
- from erpnext.non_profit.utils import get_company
- company = get_company()
- return company
-
-
-def get_additional_notes(donor, donor_details):
- if type(donor_details.notes) == dict:
- for k, v in donor_details.notes.items():
- notes = '\n'.join('{}: {}'.format(k, v))
-
- # extract donor name from notes
- if 'name' in k.lower():
- donor.update({
- 'donor_name': donor_details.notes.get(k)
- })
-
- # extract pan from notes
- if 'pan' in k.lower():
- donor.update({
- 'pan_number': donor_details.notes.get(k)
- })
-
- donor.add_comment('Comment', notes)
-
- elif type(donor_details.notes) == str:
- donor.add_comment('Comment', donor_details.notes)
-
- return donor
-
-
-def create_mode_of_payment(method):
- frappe.get_doc({
- 'doctype': 'Mode of Payment',
- 'mode_of_payment': method
- }).insert(ignore_mandatory=True)
-
-
-def notify_failure(log):
- try:
- content = '''
- Dear System Manager,
- Razorpay webhook for creating donation failed due to some reason.
- Please check the error log linked below
- Error Log: {0}
- Regards, Administrator
- '''.format(get_link_to_form('Error Log', log.name))
-
- sendmail_to_system_managers(_('[Important] [ERPNext] Razorpay donation webhook failed, please check.'), content)
- except Exception:
- pass
diff --git a/erpnext/non_profit/doctype/donation/donation_dashboard.py b/erpnext/non_profit/doctype/donation/donation_dashboard.py
deleted file mode 100644
index 492ad62171..0000000000
--- a/erpnext/non_profit/doctype/donation/donation_dashboard.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from frappe import _
-
-
-def get_data():
- return {
- 'fieldname': 'donation',
- 'non_standard_fieldnames': {
- 'Payment Entry': 'reference_name'
- },
- 'transactions': [
- {
- 'label': _('Payment'),
- 'items': ['Payment Entry']
- }
- ]
- }
diff --git a/erpnext/non_profit/doctype/donation/test_donation.py b/erpnext/non_profit/doctype/donation/test_donation.py
deleted file mode 100644
index 5fa731a6aa..0000000000
--- a/erpnext/non_profit/doctype/donation/test_donation.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-from erpnext.non_profit.doctype.donation.donation import create_donation
-
-
-class TestDonation(unittest.TestCase):
- def setUp(self):
- create_donor_type()
- settings = frappe.get_doc('Non Profit Settings')
- settings.company = '_Test Company'
- settings.donation_company = '_Test Company'
- settings.default_donor_type = '_Test Donor'
- settings.automate_donation_payment_entries = 1
- settings.donation_debit_account = 'Debtors - _TC'
- settings.donation_payment_account = 'Cash - _TC'
- settings.creation_user = 'Administrator'
- settings.flags.ignore_permissions = True
- settings.save()
-
- def test_payment_entry_for_donations(self):
- donor = create_donor()
- create_mode_of_payment()
- payment = frappe._dict({
- 'amount': 100,
- 'method': 'Debit Card',
- 'id': 'pay_MeXAmsgeKOhq7O'
- })
- donation = create_donation(donor, payment)
-
- self.assertTrue(donation.name)
-
- # Naive test to check if at all payment entry is generated
- # This method is actually triggered from Payment Gateway
- # In any case if details were missing, this would throw an error
- donation.on_payment_authorized()
- donation.reload()
-
- self.assertEqual(donation.paid, 1)
- self.assertTrue(frappe.db.exists('Payment Entry', {'reference_no': donation.name}))
-
-
-def create_donor_type():
- if not frappe.db.exists('Donor Type', '_Test Donor'):
- frappe.get_doc({
- 'doctype': 'Donor Type',
- 'donor_type': '_Test Donor'
- }).insert()
-
-
-def create_donor():
- donor = frappe.db.exists('Donor', 'donor@test.com')
- if donor:
- return frappe.get_doc('Donor', 'donor@test.com')
- else:
- return frappe.get_doc({
- 'doctype': 'Donor',
- 'donor_name': '_Test Donor',
- 'donor_type': '_Test Donor',
- 'email': 'donor@test.com'
- }).insert()
-
-
-def create_mode_of_payment():
- if not frappe.db.exists('Mode of Payment', 'Debit Card'):
- frappe.get_doc({
- 'doctype': 'Mode of Payment',
- 'mode_of_payment': 'Debit Card',
- 'accounts': [{
- 'company': '_Test Company',
- 'default_account': 'Cash - _TC'
- }]
- }).insert()
diff --git a/erpnext/non_profit/doctype/donor/__init__.py b/erpnext/non_profit/doctype/donor/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/donor/donor.js b/erpnext/non_profit/doctype/donor/donor.js
deleted file mode 100644
index 090d5af32e..0000000000
--- a/erpnext/non_profit/doctype/donor/donor.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Donor', {
- refresh: function(frm) {
- frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Donor'};
-
- frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
-
- if(!frm.doc.__islocal) {
- frappe.contacts.render_address_and_contact(frm);
- } else {
- frappe.contacts.clear_address_and_contact(frm);
- }
-
- }
-});
diff --git a/erpnext/non_profit/doctype/donor/donor.json b/erpnext/non_profit/doctype/donor/donor.json
deleted file mode 100644
index 72f24ef922..0000000000
--- a/erpnext/non_profit/doctype/donor/donor.json
+++ /dev/null
@@ -1,110 +0,0 @@
-{
- "actions": [],
- "allow_rename": 1,
- "autoname": "field:email",
- "creation": "2017-09-19 16:20:27.510196",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "donor_name",
- "column_break_5",
- "donor_type",
- "email",
- "image",
- "address_contacts",
- "address_html",
- "column_break_9",
- "contact_html"
- ],
- "fields": [
- {
- "fieldname": "donor_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Donor Name",
- "reqd": 1
- },
- {
- "fieldname": "column_break_5",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "donor_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Donor Type",
- "options": "Donor Type",
- "reqd": 1
- },
- {
- "fieldname": "email",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Email",
- "reqd": 1,
- "unique": 1
- },
- {
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "label": "Image",
- "no_copy": 1,
- "print_hide": 1
- },
- {
- "depends_on": "eval:!doc.__islocal;",
- "fieldname": "address_contacts",
- "fieldtype": "Section Break",
- "label": "Address and Contact",
- "options": "fa fa-map-marker"
- },
- {
- "fieldname": "address_html",
- "fieldtype": "HTML",
- "label": "Address HTML"
- },
- {
- "fieldname": "column_break_9",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "contact_html",
- "fieldtype": "HTML",
- "label": "Contact HTML"
- }
- ],
- "image_field": "image",
- "links": [
- {
- "link_doctype": "Donation",
- "link_fieldname": "donor"
- }
- ],
- "modified": "2021-02-17 16:36:33.470731",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Donor",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "restrict_to_domain": "Non Profit",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "donor_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donor/donor.py b/erpnext/non_profit/doctype/donor/donor.py
deleted file mode 100644
index 058321b159..0000000000
--- a/erpnext/non_profit/doctype/donor/donor.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.model.document import Document
-
-
-class Donor(Document):
- def onload(self):
- """Load address and contacts in `__onload`"""
- load_address_and_contact(self)
-
- def validate(self):
- from frappe.utils import validate_email_address
- if self.email:
- validate_email_address(self.email.strip(), True)
diff --git a/erpnext/non_profit/doctype/donor/donor_list.js b/erpnext/non_profit/doctype/donor/donor_list.js
deleted file mode 100644
index 31d4d292e7..0000000000
--- a/erpnext/non_profit/doctype/donor/donor_list.js
+++ /dev/null
@@ -1,3 +0,0 @@
-frappe.listview_settings['Donor'] = {
- add_fields: ["donor_name", "donor_type", "image"],
-};
diff --git a/erpnext/non_profit/doctype/donor/test_donor.py b/erpnext/non_profit/doctype/donor/test_donor.py
deleted file mode 100644
index fe591c8e72..0000000000
--- a/erpnext/non_profit/doctype/donor/test_donor.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestDonor(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/donor_type/__init__.py b/erpnext/non_profit/doctype/donor_type/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.js b/erpnext/non_profit/doctype/donor_type/donor_type.js
deleted file mode 100644
index 7b1fd4fe89..0000000000
--- a/erpnext/non_profit/doctype/donor_type/donor_type.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Donor Type', {
- refresh: function() {
-
- }
-});
diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.json b/erpnext/non_profit/doctype/donor_type/donor_type.json
deleted file mode 100644
index 07118fdc82..0000000000
--- a/erpnext/non_profit/doctype/donor_type/donor_type.json
+++ /dev/null
@@ -1,94 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "field:donor_type",
- "beta": 0,
- "creation": "2017-09-19 16:19:16.639635",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "donor_type",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Donor Type",
- "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,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-12-05 07:04:36.757595",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Donor Type",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.py b/erpnext/non_profit/doctype/donor_type/donor_type.py
deleted file mode 100644
index 17dca899d5..0000000000
--- a/erpnext/non_profit/doctype/donor_type/donor_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class DonorType(Document):
- pass
diff --git a/erpnext/non_profit/doctype/donor_type/test_donor_type.py b/erpnext/non_profit/doctype/donor_type/test_donor_type.py
deleted file mode 100644
index d433733ee2..0000000000
--- a/erpnext/non_profit/doctype/donor_type/test_donor_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestDonorType(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/grant_application/__init__.py b/erpnext/non_profit/doctype/grant_application/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.js b/erpnext/non_profit/doctype/grant_application/grant_application.js
deleted file mode 100644
index 70f319b828..0000000000
--- a/erpnext/non_profit/doctype/grant_application/grant_application.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Grant Application', {
- refresh: function(frm) {
- frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Grant Application'};
-
- frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
-
- if(!frm.doc.__islocal) {
- frappe.contacts.render_address_and_contact(frm);
- } else {
- frappe.contacts.clear_address_and_contact(frm);
- }
-
- if(frm.doc.status == 'Received' && !frm.doc.email_notification_sent){
- frm.add_custom_button(__("Send Grant Review Email"), function() {
- frappe.call({
- method: "erpnext.non_profit.doctype.grant_application.grant_application.send_grant_review_emails",
- args: {
- grant_application: frm.doc.name
- }
- });
- });
- }
- }
-});
diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.json b/erpnext/non_profit/doctype/grant_application/grant_application.json
deleted file mode 100644
index 2eb2087925..0000000000
--- a/erpnext/non_profit/doctype/grant_application/grant_application.json
+++ /dev/null
@@ -1,851 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 1,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 0,
- "creation": "2017-09-21 12:02:01.206913",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "applicant_type",
- "fieldtype": "Select",
- "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": "Applicant Type",
- "length": 0,
- "no_copy": 0,
- "options": "Individual\nOrganization",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "applicant_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Name",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.applicant_type=='Organization'",
- "fieldname": "contact_person",
- "fieldtype": "Data",
- "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": "Contact Person",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "email",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Email",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Open",
- "fieldname": "status",
- "fieldtype": "Select",
- "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": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nReceived\nIn Progress\nApproved\nRejected\nExpired\nWithdrawn",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "website_url",
- "fieldtype": "Data",
- "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": "Website URL",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "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": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address_contacts",
- "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,
- "label": "Address and Contact",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-map-marker",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address_html",
- "fieldtype": "HTML",
- "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": "Address HTML",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_9",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact_html",
- "fieldtype": "HTML",
- "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": "Contact HTML",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grant_application_details",
- "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,
- "label": "Grant Application Details ",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grant_description",
- "fieldtype": "Long Text",
- "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": "Grant Description",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_15",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Currency",
- "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": "Requested Amount",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "has_any_past_grant_record",
- "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": "Has any past Grant Record",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_17",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "route",
- "fieldtype": "Data",
- "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": "Route",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "published",
- "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": "Show on Website",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "assessment_result",
- "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,
- "label": "Assessment Result",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "assessment_mark",
- "fieldtype": "Float",
- "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": "Assessment Mark (Out of 10)",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "note",
- "fieldtype": "Small Text",
- "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": "Note",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_24",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "assessment_manager",
- "fieldtype": "Link",
- "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": "Assessment Manager",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "email_notification_sent",
- "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": "Email Notification Sent",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- }
- ],
- "has_web_view": 1,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_field": "",
- "image_view": 0,
- "in_create": 0,
- "is_published_field": "published",
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-12-06 12:39:57.677899",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Grant Application",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "route": "grant-application",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "applicant_name",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.py b/erpnext/non_profit/doctype/grant_application/grant_application.py
deleted file mode 100644
index cc5e1b1442..0000000000
--- a/erpnext/non_profit/doctype/grant_application/grant_application.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.utils import get_url
-from frappe.website.website_generator import WebsiteGenerator
-
-
-class GrantApplication(WebsiteGenerator):
- _website = frappe._dict(
- condition_field = "published",
- )
-
- def validate(self):
- if not self.route: #pylint: disable=E0203
- self.route = 'grant-application/' + self.scrub(self.name)
-
- def onload(self):
- """Load address and contacts in `__onload`"""
- load_address_and_contact(self)
-
- def get_context(self, context):
- context.no_cache = True
- context.show_sidebar = True
- context.parents = [dict(label='View All Grant Applications',
- route='grant-application', title='View Grants')]
-
-def get_list_context(context):
- context.allow_guest = True
- context.no_cache = True
- context.no_breadcrumbs = True
- context.show_sidebar = True
- context.order_by = 'creation desc'
- context.introduction ='''
- Apply for new Grant Application '''
-
-@frappe.whitelist()
-def send_grant_review_emails(grant_application):
- grant = frappe.get_doc("Grant Application", grant_application)
- url = get_url('grant-application/{0}'.format(grant_application))
- frappe.sendmail(
- recipients= grant.assessment_manager,
- sender=frappe.session.user,
- subject='Grant Application for {0}'.format(grant.applicant_name),
- message=' Please Review this grant application
' + url,
- reference_doctype=grant.doctype,
- reference_name=grant.name
- )
-
- grant.status = 'In Progress'
- grant.email_notification_sent = 1
- grant.save()
- frappe.db.commit()
-
- frappe.msgprint(_("Review Invitation Sent"))
diff --git a/erpnext/non_profit/doctype/grant_application/templates/grant_application.html b/erpnext/non_profit/doctype/grant_application/templates/grant_application.html
deleted file mode 100644
index 52e8469284..0000000000
--- a/erpnext/non_profit/doctype/grant_application/templates/grant_application.html
+++ /dev/null
@@ -1,68 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
- {{ applicant_name }}
- {% if frappe.user == owner %}
- Edit Grant
- {% endif %}
-
-
-
- Organization/Indvidual
- {{ applicant_type }}
-
-
- Grant Applicant Name
- {{ applicant_name}}
-
-
- Date
- {{ frappe.format_date(creation) }}
-
-
- Status
- {{ status }}
-
-
- Email
- {{ email }}
-
-
- Q. Please outline your current situation and why you are applying for a grant?
- {{ grant_description }}
- Q. Requested grant amount
- {{ amount }}
- Q. Have you recevied grant from us before?
- {{ has_any_past_grant_record }}
- Contact
- {% if frappe.user != 'Guest' %}
-
- {% if contact_person %}
-
- Contact Person
- {{ contact_person }}
-
- {% endif %}
-
- Email
- {{ email }}
-
-
- {% else %}
- You must register and login to view contact details
- {% endif %}
-
- {% if frappe.session.user == assessment_manager %}
- {% if assessment_scale %}
- Assessment Review done
- {% endif %}
- {% else %}
- Post a New Grant
- {% endif %}
-{% endblock %}
-{% block style %}
-
-
-{% endblock %}
diff --git a/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html b/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html
deleted file mode 100644
index e375b16154..0000000000
--- a/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% if doc.published %}
-
-{% endif %}
diff --git a/erpnext/non_profit/doctype/grant_application/test_grant_application.py b/erpnext/non_profit/doctype/grant_application/test_grant_application.py
deleted file mode 100644
index ef267d7af8..0000000000
--- a/erpnext/non_profit/doctype/grant_application/test_grant_application.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestGrantApplication(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/member/__init__.py b/erpnext/non_profit/doctype/member/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/member/member.js b/erpnext/non_profit/doctype/member/member.js
deleted file mode 100644
index e58ec0f5ee..0000000000
--- a/erpnext/non_profit/doctype/member/member.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Member', {
- setup: function(frm) {
- frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => {
- if (val && (frm.doc.subscription_id || frm.doc.customer_id)) {
- frm.set_df_property('razorpay_details_section', 'hidden', false);
- }
- })
- },
-
- refresh: function(frm) {
-
- frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Member'};
-
- frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
-
- if(!frm.doc.__islocal) {
- frappe.contacts.render_address_and_contact(frm);
-
- // custom buttons
- frm.add_custom_button(__('Accounting Ledger'), function() {
- frappe.set_route('query-report', 'General Ledger',
- {party_type:'Member', party:frm.doc.name});
- });
-
- frm.add_custom_button(__('Accounts Receivable'), function() {
- frappe.set_route('query-report', 'Accounts Receivable', {member:frm.doc.name});
- });
-
- if (!frm.doc.customer) {
- frm.add_custom_button(__('Create Customer'), () => {
- frm.call('make_customer_and_link').then(() => {
- frm.reload_doc();
- });
- });
- }
-
- // indicator
- erpnext.utils.set_party_dashboard_indicators(frm);
-
- } else {
- frappe.contacts.clear_address_and_contact(frm);
- }
-
- frappe.call({
- method:"frappe.client.get_value",
- args:{
- 'doctype':"Membership",
- 'filters':{'member': frm.doc.name},
- 'fieldname':[
- 'to_date'
- ]
- },
- callback: function (data) {
- if(data.message) {
- frappe.model.set_value(frm.doctype,frm.docname,
- "membership_expiry_date", data.message.to_date);
- }
- }
- });
- }
-});
diff --git a/erpnext/non_profit/doctype/member/member.json b/erpnext/non_profit/doctype/member/member.json
deleted file mode 100644
index 7c1baf1a8d..0000000000
--- a/erpnext/non_profit/doctype/member/member.json
+++ /dev/null
@@ -1,210 +0,0 @@
-{
- "actions": [],
- "allow_rename": 1,
- "autoname": "naming_series:",
- "creation": "2017-09-11 09:24:52.898356",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "naming_series",
- "member_name",
- "membership_expiry_date",
- "column_break_5",
- "membership_type",
- "email_id",
- "image",
- "customer_section",
- "customer",
- "customer_name",
- "supplier_section",
- "supplier",
- "address_contacts",
- "address_html",
- "column_break_9",
- "contact_html",
- "razorpay_details_section",
- "subscription_id",
- "customer_id",
- "subscription_status",
- "column_break_21",
- "subscription_start",
- "subscription_end"
- ],
- "fields": [
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Series",
- "options": "NPO-MEM-.YYYY.-",
- "reqd": 1
- },
- {
- "fieldname": "member_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Member Name",
- "reqd": 1
- },
- {
- "fieldname": "membership_expiry_date",
- "fieldtype": "Date",
- "label": "Membership Expiry Date"
- },
- {
- "fieldname": "column_break_5",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "membership_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Membership Type",
- "options": "Membership Type",
- "reqd": 1
- },
- {
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "label": "Image",
- "no_copy": 1,
- "print_hide": 1
- },
- {
- "collapsible": 1,
- "fieldname": "customer_section",
- "fieldtype": "Section Break",
- "label": "Customer"
- },
- {
- "fieldname": "customer",
- "fieldtype": "Link",
- "label": "Customer",
- "options": "Customer"
- },
- {
- "fetch_from": "customer.customer_name",
- "fieldname": "customer_name",
- "fieldtype": "Data",
- "label": "Customer Name",
- "read_only": 1
- },
- {
- "collapsible": 1,
- "fieldname": "supplier_section",
- "fieldtype": "Section Break",
- "label": "Supplier"
- },
- {
- "fieldname": "supplier",
- "fieldtype": "Link",
- "label": "Supplier",
- "options": "Supplier"
- },
- {
- "depends_on": "eval:!doc.__islocal;",
- "fieldname": "address_contacts",
- "fieldtype": "Section Break",
- "label": "Address and Contact",
- "options": "fa fa-map-marker"
- },
- {
- "fieldname": "address_html",
- "fieldtype": "HTML",
- "label": "Address HTML"
- },
- {
- "fieldname": "column_break_9",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "contact_html",
- "fieldtype": "HTML",
- "label": "Contact HTML"
- },
- {
- "fieldname": "email_id",
- "fieldtype": "Data",
- "label": "Email Address",
- "options": "Email"
- },
- {
- "fieldname": "subscription_id",
- "fieldtype": "Data",
- "label": "Subscription ID",
- "read_only": 1
- },
- {
- "fieldname": "customer_id",
- "fieldtype": "Data",
- "label": "Customer ID",
- "read_only": 1
- },
- {
- "fieldname": "razorpay_details_section",
- "fieldtype": "Section Break",
- "hidden": 1,
- "label": "Razorpay Details"
- },
- {
- "fieldname": "column_break_21",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "subscription_start",
- "fieldtype": "Date",
- "label": "Subscription Start "
- },
- {
- "fieldname": "subscription_end",
- "fieldtype": "Date",
- "label": "Subscription End"
- },
- {
- "fieldname": "subscription_status",
- "fieldtype": "Select",
- "label": "Subscription Status",
- "options": "\nActive\nHalted"
- }
- ],
- "image_field": "image",
- "links": [],
- "modified": "2021-07-11 14:27:26.368039",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Member",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Member",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "restrict_to_domain": "Non Profit",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "member_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
deleted file mode 100644
index 4d80e57ecc..0000000000
--- a/erpnext/non_profit/doctype/member/member.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.integrations.utils import get_payment_gateway_controller
-from frappe.model.document import Document
-from frappe.utils import cint, get_link_to_form
-
-from erpnext.non_profit.doctype.membership_type.membership_type import get_membership_type
-
-
-class Member(Document):
- def onload(self):
- """Load address and contacts in `__onload`"""
- load_address_and_contact(self)
-
-
- def validate(self):
- if self.email_id:
- self.validate_email_type(self.email_id)
-
- def validate_email_type(self, email):
- from frappe.utils import validate_email_address
- validate_email_address(email.strip(), True)
-
- def setup_subscription(self):
- non_profit_settings = frappe.get_doc('Non Profit Settings')
- if not non_profit_settings.enable_razorpay_for_memberships:
- frappe.throw(_('Please check Enable Razorpay for Memberships in {0} to setup subscription')).format(
- get_link_to_form('Non Profit Settings', 'Non Profit Settings'))
-
- controller = get_payment_gateway_controller("Razorpay")
- settings = controller.get_settings({})
-
- plan_id = frappe.get_value("Membership Type", self.membership_type, "razorpay_plan_id")
-
- if not plan_id:
- frappe.throw(_("Please setup Razorpay Plan ID"))
-
- subscription_details = {
- "plan_id": plan_id,
- "billing_frequency": cint(non_profit_settings.billing_frequency),
- "customer_notify": 1
- }
-
- args = {
- 'subscription_details': subscription_details
- }
-
- subscription = controller.setup_subscription(settings, **args)
-
- return subscription
-
- @frappe.whitelist()
- def make_customer_and_link(self):
- if self.customer:
- frappe.msgprint(_("A customer is already linked to this Member"))
-
- customer = create_customer(frappe._dict({
- 'fullname': self.member_name,
- 'email': self.email_id,
- 'phone': None
- }))
-
- self.customer = customer
- self.save()
- frappe.msgprint(_("Customer {0} has been created succesfully.").format(self.customer))
-
-
-def get_or_create_member(user_details):
- member_list = frappe.get_all("Member", filters={'email': user_details.email, 'membership_type': user_details.plan_id})
- if member_list and member_list[0]:
- return member_list[0]['name']
- else:
- return create_member(user_details)
-
-def create_member(user_details):
- user_details = frappe._dict(user_details)
- member = frappe.new_doc("Member")
- member.update({
- "member_name": user_details.fullname,
- "email_id": user_details.email,
- "pan_number": user_details.pan or None,
- "membership_type": user_details.plan_id,
- "customer_id": user_details.customer_id or None,
- "subscription_id": user_details.subscription_id or None,
- "subscription_status": user_details.subscription_status or ""
- })
-
- member.insert(ignore_permissions=True)
- member.customer = create_customer(user_details, member.name)
- member.save(ignore_permissions=True)
-
- return member
-
-def create_customer(user_details, member=None):
- customer = frappe.new_doc("Customer")
- customer.customer_name = user_details.fullname
- customer.customer_type = "Individual"
- customer.flags.ignore_mandatory = True
- customer.insert(ignore_permissions=True)
-
- try:
- contact = frappe.new_doc("Contact")
- contact.first_name = user_details.fullname
- if user_details.mobile:
- contact.add_phone(user_details.mobile, is_primary_phone=1, is_primary_mobile_no=1)
- if user_details.email:
- contact.add_email(user_details.email, is_primary=1)
- contact.insert(ignore_permissions=True)
-
- contact.append("links", {
- "link_doctype": "Customer",
- "link_name": customer.name
- })
-
- if member:
- contact.append("links", {
- "link_doctype": "Member",
- "link_name": member
- })
-
- contact.save(ignore_permissions=True)
-
- except frappe.DuplicateEntryError:
- return customer.name
-
- except Exception as e:
- frappe.log_error(frappe.get_traceback(), _("Contact Creation Failed"))
- pass
-
- return customer.name
-
-@frappe.whitelist(allow_guest=True)
-def create_member_subscription_order(user_details):
- """Create Member subscription and order for payment
-
- Args:
- user_details (TYPE): Description
-
- Returns:
- Dictionary: Dictionary with subscription details
- {
- 'subscription_details': {
- 'plan_id': 'plan_EXwyxDYDCj3X4v',
- 'billing_frequency': 24,
- 'customer_notify': 1
- },
- 'subscription_id': 'sub_EZycCvXFvqnC6p'
- }
- """
-
- user_details = frappe._dict(user_details)
- member = get_or_create_member(user_details)
-
- subscription = member.setup_subscription()
-
- member.subscription_id = subscription.get('subscription_id')
- member.save(ignore_permissions=True)
-
- return subscription
-
-@frappe.whitelist()
-def register_member(fullname, email, rzpay_plan_id, subscription_id, pan=None, mobile=None):
- plan = get_membership_type(rzpay_plan_id)
- if not plan:
- raise frappe.DoesNotExistError
-
- member = frappe.db.exists("Member", {'email': email, 'subscription_id': subscription_id })
- if member:
- return member
- else:
- member = create_member(dict(
- fullname=fullname,
- email=email,
- plan_id=plan,
- subscription_id=subscription_id,
- pan=pan,
- mobile=mobile
- ))
-
- return member.name
diff --git a/erpnext/non_profit/doctype/member/member_dashboard.py b/erpnext/non_profit/doctype/member/member_dashboard.py
deleted file mode 100644
index 0e31e3ceb8..0000000000
--- a/erpnext/non_profit/doctype/member/member_dashboard.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from frappe import _
-
-
-def get_data():
- return {
- 'heatmap': True,
- 'heatmap_message': _('Member Activity'),
- 'fieldname': 'member',
- 'non_standard_fieldnames': {
- 'Bank Account': 'party'
- },
- 'transactions': [
- {
- 'label': _('Membership Details'),
- 'items': ['Membership']
- },
- {
- 'label': _('Fee'),
- 'items': ['Bank Account']
- }
- ]
- }
diff --git a/erpnext/non_profit/doctype/member/member_list.js b/erpnext/non_profit/doctype/member/member_list.js
deleted file mode 100644
index 8e41e7fdde..0000000000
--- a/erpnext/non_profit/doctype/member/member_list.js
+++ /dev/null
@@ -1,3 +0,0 @@
-frappe.listview_settings['Member'] = {
- add_fields: ["member_name", "membership_type", "image"],
-};
diff --git a/erpnext/non_profit/doctype/member/test_member.py b/erpnext/non_profit/doctype/member/test_member.py
deleted file mode 100644
index 46f14ed131..0000000000
--- a/erpnext/non_profit/doctype/member/test_member.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestMember(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/membership/__init__.py b/erpnext/non_profit/doctype/membership/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/membership/membership.js b/erpnext/non_profit/doctype/membership/membership.js
deleted file mode 100644
index 31872048a0..0000000000
--- a/erpnext/non_profit/doctype/membership/membership.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Membership', {
- setup: function(frm) {
- frappe.db.get_single_value("Non Profit Settings", "enable_razorpay_for_memberships").then(val => {
- if (val) frm.set_df_property("razorpay_details_section", "hidden", false);
- })
- },
-
- refresh: function(frm) {
- if (frm.doc.__islocal)
- return;
-
- !frm.doc.invoice && frm.add_custom_button("Generate Invoice", () => {
- frm.call({
- doc: frm.doc,
- method: "generate_invoice",
- args: {save: true},
- freeze: true,
- freeze_message: __("Creating Membership Invoice"),
- callback: function(r) {
- if (r.invoice)
- frm.reload_doc();
- }
- });
- });
-
- frappe.db.get_single_value("Non Profit Settings", "send_email").then(val => {
- if (val) frm.add_custom_button("Send Acknowledgement", () => {
- frm.call("send_acknowlement").then(() => {
- frm.reload_doc();
- });
- });
- })
- },
-
- onload: function(frm) {
- frm.add_fetch("membership_type", "amount", "amount");
- }
-});
diff --git a/erpnext/non_profit/doctype/membership/membership.json b/erpnext/non_profit/doctype/membership/membership.json
deleted file mode 100644
index 11d32f9c2b..0000000000
--- a/erpnext/non_profit/doctype/membership/membership.json
+++ /dev/null
@@ -1,184 +0,0 @@
-{
- "actions": [],
- "autoname": "NPO-MSH-.YYYY.-.#####",
- "creation": "2017-09-11 11:39:18.492184",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "member",
- "member_name",
- "membership_type",
- "column_break_3",
- "company",
- "membership_status",
- "membership_validity_section",
- "from_date",
- "to_date",
- "column_break_8",
- "member_since_date",
- "payment_details",
- "paid",
- "currency",
- "amount",
- "invoice",
- "razorpay_details_section",
- "subscription_id",
- "payment_id"
- ],
- "fields": [
- {
- "fieldname": "member",
- "fieldtype": "Link",
- "label": "Member",
- "options": "Member"
- },
- {
- "fieldname": "membership_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Membership Type",
- "options": "Membership Type",
- "reqd": 1
- },
- {
- "fieldname": "column_break_3",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "membership_status",
- "fieldtype": "Select",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Membership Status",
- "options": "New\nCurrent\nExpired\nPending\nCancelled"
- },
- {
- "fieldname": "membership_validity_section",
- "fieldtype": "Section Break",
- "label": "Validity"
- },
- {
- "fieldname": "from_date",
- "fieldtype": "Date",
- "in_list_view": 1,
- "label": "From",
- "reqd": 1
- },
- {
- "fieldname": "to_date",
- "fieldtype": "Date",
- "in_list_view": 1,
- "label": "To",
- "reqd": 1
- },
- {
- "fieldname": "column_break_8",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "member_since_date",
- "fieldtype": "Date",
- "label": "Member Since"
- },
- {
- "fieldname": "payment_details",
- "fieldtype": "Section Break",
- "label": "Payment Details"
- },
- {
- "default": "0",
- "fieldname": "paid",
- "fieldtype": "Check",
- "label": "Paid"
- },
- {
- "fieldname": "currency",
- "fieldtype": "Link",
- "label": "Currency",
- "options": "Currency"
- },
- {
- "fieldname": "amount",
- "fieldtype": "Float",
- "label": "Amount"
- },
- {
- "fieldname": "razorpay_details_section",
- "fieldtype": "Section Break",
- "hidden": 1,
- "label": "Razorpay Details"
- },
- {
- "fieldname": "subscription_id",
- "fieldtype": "Data",
- "label": "Subscription ID",
- "read_only": 1
- },
- {
- "fieldname": "payment_id",
- "fieldtype": "Data",
- "label": "Payment ID",
- "read_only": 1
- },
- {
- "fieldname": "invoice",
- "fieldtype": "Link",
- "label": "Invoice",
- "options": "Sales Invoice"
- },
- {
- "fetch_from": "member.member_name",
- "fieldname": "member_name",
- "fieldtype": "Data",
- "label": "Member Name",
- "read_only": 1
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "reqd": 1
- }
- ],
- "index_web_pages_for_search": 1,
- "links": [],
- "modified": "2021-02-19 14:33:44.925122",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Membership",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Member",
- "share": 1,
- "write": 1
- }
- ],
- "restrict_to_domain": "Non Profit",
- "search_fields": "member, member_name",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "member_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership/membership_list.js b/erpnext/non_profit/doctype/membership/membership_list.js
deleted file mode 100644
index a959159899..0000000000
--- a/erpnext/non_profit/doctype/membership/membership_list.js
+++ /dev/null
@@ -1,15 +0,0 @@
-frappe.listview_settings['Membership'] = {
- get_indicator: function(doc) {
- if (doc.membership_status == 'New') {
- return [__('New'), 'blue', 'membership_status,=,New'];
- } else if (doc.membership_status === 'Current') {
- return [__('Current'), 'green', 'membership_status,=,Current'];
- } else if (doc.membership_status === 'Pending') {
- return [__('Pending'), 'yellow', 'membership_status,=,Pending'];
- } else if (doc.membership_status === 'Expired') {
- return [__('Expired'), 'grey', 'membership_status,=,Expired'];
- } else {
- return [__('Cancelled'), 'red', 'membership_status,=,Cancelled'];
- }
- }
-};
diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py
deleted file mode 100644
index fbe344c6a1..0000000000
--- a/erpnext/non_profit/doctype/membership/test_membership.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-from frappe.utils import add_months, nowdate
-
-import erpnext
-from erpnext.non_profit.doctype.member.member import create_member
-from erpnext.non_profit.doctype.membership.membership import update_halted_razorpay_subscription
-
-
-class TestMembership(unittest.TestCase):
- def setUp(self):
- plan = setup_membership()
-
- # make test member
- self.member_doc = create_member(
- frappe._dict({
- "fullname": "_Test_Member",
- "email": "_test_member_erpnext@example.com",
- "plan_id": plan.name,
- "subscription_id": "sub_DEX6xcJ1HSW4CR",
- "customer_id": "cust_C0WlbKhp3aLA7W",
- "subscription_status": "Active"
- })
- )
- self.member_doc.make_customer_and_link()
- self.member = self.member_doc.name
-
- def test_auto_generate_invoice_and_payment_entry(self):
- entry = make_membership(self.member)
-
- # Naive test to see if at all invoice was generated and attached to member
- # In any case if details were missing, the invoicing would throw an error
- invoice = entry.generate_invoice(save=True)
- self.assertEqual(invoice.name, entry.invoice)
-
- def test_renew_within_30_days(self):
- # create a membership for two months
- # Should work fine
- make_membership(self.member, { "from_date": nowdate() })
- make_membership(self.member, { "from_date": add_months(nowdate(), 1) })
-
- from frappe.utils.user import add_role
- add_role("test@example.com", "Non Profit Manager")
- frappe.set_user("test@example.com")
-
- # create next membership with expiry not within 30 days
- self.assertRaises(frappe.ValidationError, make_membership, self.member, {
- "from_date": add_months(nowdate(), 2),
- })
-
- frappe.set_user("Administrator")
- # create the same membership but as administrator
- make_membership(self.member, {
- "from_date": add_months(nowdate(), 2),
- "to_date": add_months(nowdate(), 3),
- })
-
- def test_halted_memberships(self):
- make_membership(self.member, {
- "from_date": add_months(nowdate(), 2),
- "to_date": add_months(nowdate(), 3)
- })
-
- self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Active")
- payload = get_subscription_payload()
- update_halted_razorpay_subscription(data=payload)
- self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Halted")
-
- def tearDown(self):
- frappe.db.rollback()
-
-def set_config(key, value):
- frappe.db.set_value("Non Profit Settings", None, key, value)
-
-def make_membership(member, payload={}):
- data = {
- "doctype": "Membership",
- "member": member,
- "membership_status": "Current",
- "membership_type": "_rzpy_test_milythm",
- "currency": "INR",
- "paid": 1,
- "from_date": nowdate(),
- "amount": 100
- }
- data.update(payload)
- membership = frappe.get_doc(data)
- membership.insert(ignore_permissions=True, ignore_if_duplicate=True)
- return membership
-
-def create_item(item_code):
- if not frappe.db.exists("Item", item_code):
- item = frappe.new_doc("Item")
- item.item_code = item_code
- item.item_name = item_code
- item.stock_uom = "Nos"
- item.description = item_code
- item.item_group = "All Item Groups"
- item.is_stock_item = 0
- item.save()
- else:
- item = frappe.get_doc("Item", item_code)
- return item
-
-def setup_membership():
- # Get default company
- company = frappe.get_doc("Company", erpnext.get_default_company())
-
- # update non profit settings
- settings = frappe.get_doc("Non Profit Settings")
- # Enable razorpay
- settings.enable_razorpay_for_memberships = 1
- settings.billing_cycle = "Monthly"
- settings.billing_frequency = 24
- # Enable invoicing
- settings.allow_invoicing = 1
- settings.automate_membership_payment_entries = 1
- settings.company = company.name
- settings.donation_company = company.name
- settings.membership_payment_account = company.default_cash_account
- settings.membership_debit_account = company.default_receivable_account
- settings.flags.ignore_mandatory = True
- settings.save()
-
- # make test plan
- if not frappe.db.exists("Membership Type", "_rzpy_test_milythm"):
- plan = frappe.new_doc("Membership Type")
- plan.membership_type = "_rzpy_test_milythm"
- plan.amount = 100
- plan.razorpay_plan_id = "_rzpy_test_milythm"
- plan.linked_item = create_item("_Test Item for Non Profit Membership").name
- plan.insert()
- else:
- plan = frappe.get_doc("Membership Type", "_rzpy_test_milythm")
-
- return plan
-
-def get_subscription_payload():
- return {
- "entity": "event",
- "account_id": "acc_BFQ7uQEaa7j2z7",
- "event": "subscription.halted",
- "contains": [
- "subscription"
- ],
- "payload": {
- "subscription": {
- "entity": {
- "id": "sub_DEX6xcJ1HSW4CR",
- "entity": "subscription",
- "plan_id": "_rzpy_test_milythm",
- "customer_id": "cust_C0WlbKhp3aLA7W",
- "status": "halted",
- "notes": {
- "Important": "Notes for Internal Reference"
- },
- }
- }
- }
- }
diff --git a/erpnext/non_profit/doctype/membership_type/__init__.py b/erpnext/non_profit/doctype/membership_type/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.js b/erpnext/non_profit/doctype/membership_type/membership_type.js
deleted file mode 100644
index 2f2427629c..0000000000
--- a/erpnext/non_profit/doctype/membership_type/membership_type.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Membership Type', {
- refresh: function (frm) {
- frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => {
- if (val) frm.set_df_property('razorpay_plan_id', 'hidden', false);
- });
-
- frappe.db.get_single_value('Non Profit Settings', 'allow_invoicing').then(val => {
- if (val) frm.set_df_property('linked_item', 'hidden', false);
- });
-
- frm.set_query('linked_item', () => {
- return {
- filters: {
- is_stock_item: 0
- }
- };
- });
- }
-});
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.json b/erpnext/non_profit/doctype/membership_type/membership_type.json
deleted file mode 100644
index 6ce1ecde12..0000000000
--- a/erpnext/non_profit/doctype/membership_type/membership_type.json
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "actions": [],
- "autoname": "field:membership_type",
- "creation": "2017-09-18 12:56:56.343999",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "membership_type",
- "amount",
- "razorpay_plan_id",
- "linked_item"
- ],
- "fields": [
- {
- "fieldname": "membership_type",
- "fieldtype": "Data",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Membership Type",
- "reqd": 1,
- "unique": 1
- },
- {
- "fieldname": "amount",
- "fieldtype": "Float",
- "in_list_view": 1,
- "label": "Amount",
- "reqd": 1
- },
- {
- "fieldname": "razorpay_plan_id",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Razorpay Plan ID",
- "unique": 1
- },
- {
- "fieldname": "linked_item",
- "fieldtype": "Link",
- "label": "Linked Item",
- "options": "Item",
- "unique": 1
- }
- ],
- "links": [],
- "modified": "2020-08-05 15:21:43.595745",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Membership Type",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "restrict_to_domain": "Non Profit",
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.py b/erpnext/non_profit/doctype/membership_type/membership_type.py
deleted file mode 100644
index b446421571..0000000000
--- a/erpnext/non_profit/doctype/membership_type/membership_type.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-
-class MembershipType(Document):
- def validate(self):
- if self.linked_item:
- is_stock_item = frappe.db.get_value("Item", self.linked_item, "is_stock_item")
- if is_stock_item:
- frappe.throw(_("The Linked Item should be a service item"))
-
-def get_membership_type(razorpay_id):
- return frappe.db.exists("Membership Type", {"razorpay_plan_id": razorpay_id})
diff --git a/erpnext/non_profit/doctype/membership_type/test_membership_type.py b/erpnext/non_profit/doctype/membership_type/test_membership_type.py
deleted file mode 100644
index 98bc087acd..0000000000
--- a/erpnext/non_profit/doctype/membership_type/test_membership_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestMembershipType(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/non_profit_settings/__init__.py b/erpnext/non_profit/doctype/non_profit_settings/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js
deleted file mode 100644
index 4c4ca9834b..0000000000
--- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on("Non Profit Settings", {
- refresh: function(frm) {
- frm.set_query("inv_print_format", function() {
- return {
- filters: {
- "doc_type": "Sales Invoice"
- }
- };
- });
-
- frm.set_query("membership_print_format", function() {
- return {
- filters: {
- "doc_type": "Membership"
- }
- };
- });
-
- frm.set_query("membership_debit_account", function() {
- return {
- filters: {
- "account_type": "Receivable",
- "is_group": 0,
- "company": frm.doc.company
- }
- };
- });
-
- frm.set_query("donation_debit_account", function() {
- return {
- filters: {
- "account_type": "Receivable",
- "is_group": 0,
- "company": frm.doc.donation_company
- }
- };
- });
-
- frm.set_query("membership_payment_account", function () {
- var account_types = ["Bank", "Cash"];
- return {
- filters: {
- "account_type": ["in", account_types],
- "is_group": 0,
- "company": frm.doc.company
- }
- };
- });
-
- frm.set_query("donation_payment_account", function () {
- var account_types = ["Bank", "Cash"];
- return {
- filters: {
- "account_type": ["in", account_types],
- "is_group": 0,
- "company": frm.doc.donation_company
- }
- };
- });
-
- let docs_url = "https://docs.erpnext.com/docs/user/manual/en/non_profit/membership";
-
- frm.set_intro(__("You can learn more about memberships in the manual. ") + `${__('ERPNext Docs')} `, true);
- frm.trigger("setup_buttons_for_membership");
- frm.trigger("setup_buttons_for_donation");
- },
-
- setup_buttons_for_membership: function(frm) {
- let label;
-
- if (frm.doc.membership_webhook_secret) {
-
- frm.add_custom_button(__("Copy Webhook URL"), () => {
- frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.membership.membership.trigger_razorpay_subscription`);
- }, __("Memberships"));
-
- frm.add_custom_button(__("Revoke Key"), () => {
- frm.call("revoke_key", {
- key: "membership_webhook_secret"
- }).then(() => {
- frm.refresh();
- });
- }, __("Memberships"));
-
- label = __("Regenerate Webhook Secret");
-
- } else {
- label = __("Generate Webhook Secret");
- }
-
- frm.add_custom_button(label, () => {
- frm.call("generate_webhook_secret", {
- field: "membership_webhook_secret"
- }).then(() => {
- frm.refresh();
- });
- }, __("Memberships"));
- },
-
- setup_buttons_for_donation: function(frm) {
- let label;
-
- if (frm.doc.donation_webhook_secret) {
- label = __("Regenerate Webhook Secret");
-
- frm.add_custom_button(__("Copy Webhook URL"), () => {
- frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.donation.donation.capture_razorpay_donations`);
- }, __("Donations"));
-
- frm.add_custom_button(__("Revoke Key"), () => {
- frm.call("revoke_key", {
- key: "donation_webhook_secret"
- }).then(() => {
- frm.refresh();
- });
- }, __("Donations"));
-
- } else {
- label = __("Generate Webhook Secret");
- }
-
- frm.add_custom_button(label, () => {
- frm.call("generate_webhook_secret", {
- field: "donation_webhook_secret"
- }).then(() => {
- frm.refresh();
- });
- }, __("Donations"));
- }
-});
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json
deleted file mode 100644
index 25ff0c1bb0..0000000000
--- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json
+++ /dev/null
@@ -1,273 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-29 12:57:03.005120",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "enable_razorpay_for_memberships",
- "razorpay_settings_section",
- "billing_cycle",
- "billing_frequency",
- "membership_webhook_secret",
- "column_break_6",
- "allow_invoicing",
- "automate_membership_invoicing",
- "automate_membership_payment_entries",
- "company",
- "membership_debit_account",
- "membership_payment_account",
- "column_break_9",
- "send_email",
- "send_invoice",
- "membership_print_format",
- "inv_print_format",
- "email_template",
- "donation_settings_section",
- "donation_company",
- "default_donor_type",
- "donation_webhook_secret",
- "column_break_22",
- "automate_donation_payment_entries",
- "donation_debit_account",
- "donation_payment_account",
- "section_break_27",
- "creation_user"
- ],
- "fields": [
- {
- "fieldname": "billing_cycle",
- "fieldtype": "Select",
- "label": "Billing Cycle",
- "options": "Monthly\nYearly"
- },
- {
- "depends_on": "eval:doc.enable_razorpay_for_memberships",
- "fieldname": "razorpay_settings_section",
- "fieldtype": "Section Break",
- "label": "RazorPay Settings for Memberships"
- },
- {
- "description": "The number of billing cycles for which the customer should be charged. For example, if a customer is buying a 1-year membership that should be billed on a monthly basis, this value should be 12.",
- "fieldname": "billing_frequency",
- "fieldtype": "Int",
- "label": "Billing Frequency"
- },
- {
- "fieldname": "column_break_6",
- "fieldtype": "Section Break",
- "label": "Membership Invoicing"
- },
- {
- "fieldname": "column_break_9",
- "fieldtype": "Column Break"
- },
- {
- "description": "This company will be set for the Memberships created via webhook.",
- "fieldname": "company",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "default": "0",
- "depends_on": "eval:doc.allow_invoicing && doc.send_email",
- "fieldname": "send_invoice",
- "fieldtype": "Check",
- "label": "Send Invoice with Email"
- },
- {
- "default": "0",
- "fieldname": "send_email",
- "fieldtype": "Check",
- "label": "Send Membership Acknowledgement"
- },
- {
- "depends_on": "eval: doc.send_invoice",
- "fieldname": "inv_print_format",
- "fieldtype": "Link",
- "label": "Invoice Print Format",
- "mandatory_depends_on": "eval: doc.send_invoice",
- "options": "Print Format"
- },
- {
- "depends_on": "eval:doc.send_email",
- "fieldname": "membership_print_format",
- "fieldtype": "Link",
- "label": "Membership Print Format",
- "options": "Print Format"
- },
- {
- "depends_on": "eval:doc.send_email",
- "fieldname": "email_template",
- "fieldtype": "Link",
- "label": "Email Template",
- "mandatory_depends_on": "eval:doc.send_email",
- "options": "Email Template"
- },
- {
- "default": "0",
- "fieldname": "allow_invoicing",
- "fieldtype": "Check",
- "label": "Allow Invoicing for Memberships",
- "mandatory_depends_on": "eval:doc.send_invoice || doc.make_payment_entry"
- },
- {
- "default": "0",
- "depends_on": "eval:doc.allow_invoicing",
- "description": "Automatically create an invoice when payment is authorized from a web form entry",
- "fieldname": "automate_membership_invoicing",
- "fieldtype": "Check",
- "label": "Automate Invoicing for Web Forms"
- },
- {
- "default": "0",
- "depends_on": "eval:doc.allow_invoicing",
- "description": "Auto creates Payment Entry for Sales Invoices created for Membership from web forms.",
- "fieldname": "automate_membership_payment_entries",
- "fieldtype": "Check",
- "label": "Automate Payment Entry Creation"
- },
- {
- "default": "0",
- "fieldname": "enable_razorpay_for_memberships",
- "fieldtype": "Check",
- "label": "Enable RazorPay For Memberships"
- },
- {
- "depends_on": "eval:doc.automate_membership_payment_entries",
- "description": "Account for accepting membership payments",
- "fieldname": "membership_payment_account",
- "fieldtype": "Link",
- "label": "Membership Payment To",
- "mandatory_depends_on": "eval:doc.automate_membership_payment_entries",
- "options": "Account"
- },
- {
- "fieldname": "membership_webhook_secret",
- "fieldtype": "Password",
- "label": "Membership Webhook Secret",
- "read_only": 1
- },
- {
- "fieldname": "donation_webhook_secret",
- "fieldtype": "Password",
- "label": "Donation Webhook Secret",
- "read_only": 1
- },
- {
- "depends_on": "automate_donation_payment_entries",
- "description": "Account for accepting donation payments",
- "fieldname": "donation_payment_account",
- "fieldtype": "Link",
- "label": "Donation Payment To",
- "mandatory_depends_on": "automate_donation_payment_entries",
- "options": "Account"
- },
- {
- "default": "0",
- "description": "Auto creates Payment Entry for Donations created from web forms.",
- "fieldname": "automate_donation_payment_entries",
- "fieldtype": "Check",
- "label": "Automate Donation Payment Entries"
- },
- {
- "depends_on": "eval:doc.allow_invoicing",
- "fieldname": "membership_debit_account",
- "fieldtype": "Link",
- "label": "Debit Account",
- "mandatory_depends_on": "eval:doc.allow_invoicing",
- "options": "Account"
- },
- {
- "depends_on": "automate_donation_payment_entries",
- "fieldname": "donation_debit_account",
- "fieldtype": "Link",
- "label": "Debit Account",
- "mandatory_depends_on": "automate_donation_payment_entries",
- "options": "Account"
- },
- {
- "description": "This company will be set for the Donations created via webhook.",
- "fieldname": "donation_company",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "fieldname": "donation_settings_section",
- "fieldtype": "Section Break",
- "label": "Donation Settings"
- },
- {
- "fieldname": "column_break_22",
- "fieldtype": "Column Break"
- },
- {
- "description": "This Donor Type will be set for the Donor created via Donation web form entry.",
- "fieldname": "default_donor_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Default Donor Type",
- "options": "Donor Type",
- "reqd": 1
- },
- {
- "fieldname": "section_break_27",
- "fieldtype": "Section Break"
- },
- {
- "description": "The user that will be used to create Donations, Memberships, Invoices, and Payment Entries. This user should have the relevant permissions.",
- "fieldname": "creation_user",
- "fieldtype": "Link",
- "label": "Creation User",
- "options": "User",
- "reqd": 1
- }
- ],
- "index_web_pages_for_search": 1,
- "issingle": 1,
- "links": [],
- "modified": "2021-03-11 10:43:38.124240",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Non Profit Settings",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- },
- {
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "Non Profit Member",
- "share": 1
- }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py
deleted file mode 100644
index ace6605542..0000000000
--- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.integrations.utils import get_payment_gateway_controller
-from frappe.model.document import Document
-
-
-class NonProfitSettings(Document):
- @frappe.whitelist()
- def generate_webhook_secret(self, field="membership_webhook_secret"):
- key = frappe.generate_hash(length=20)
- self.set(field, key)
- self.save()
-
- secret_for = "Membership" if field == "membership_webhook_secret" else "Donation"
-
- frappe.msgprint(
- _("Here is your webhook secret for {0} API, this will be shown to you only once.").format(secret_for) + " " + key,
- _("Webhook Secret")
- )
-
- @frappe.whitelist()
- def revoke_key(self, key):
- self.set(key, None)
- self.save()
-
- def get_webhook_secret(self, endpoint="Membership"):
- fieldname = "membership_webhook_secret" if endpoint == "Membership" else "donation_webhook_secret"
- return self.get_password(fieldname=fieldname, raise_exception=False)
-
-@frappe.whitelist()
-def get_plans_for_membership(*args, **kwargs):
- controller = get_payment_gateway_controller("Razorpay")
- plans = controller.get_plans()
- return [plan.get("item") for plan in plans.get("items")]
diff --git a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
deleted file mode 100644
index 51d1ba02eb..0000000000
--- a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-# import frappe
-import unittest
-
-
-class TestNonProfitSettings(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/volunteer/__init__.py b/erpnext/non_profit/doctype/volunteer/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/volunteer/test_volunteer.py b/erpnext/non_profit/doctype/volunteer/test_volunteer.py
deleted file mode 100644
index 0a0ab2cf34..0000000000
--- a/erpnext/non_profit/doctype/volunteer/test_volunteer.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestVolunteer(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.js b/erpnext/non_profit/doctype/volunteer/volunteer.js
deleted file mode 100644
index ac93d8c801..0000000000
--- a/erpnext/non_profit/doctype/volunteer/volunteer.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Volunteer', {
- refresh: function(frm) {
-
- frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Volunteer'};
-
- frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
-
- if(!frm.doc.__islocal) {
- frappe.contacts.render_address_and_contact(frm);
- } else {
- frappe.contacts.clear_address_and_contact(frm);
- }
- }
-});
diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.json b/erpnext/non_profit/doctype/volunteer/volunteer.json
deleted file mode 100644
index 08b7f87b2a..0000000000
--- a/erpnext/non_profit/doctype/volunteer/volunteer.json
+++ /dev/null
@@ -1,148 +0,0 @@
-{
- "actions": [],
- "allow_rename": 1,
- "autoname": "field:email",
- "creation": "2017-09-19 16:16:45.676019",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "volunteer_name",
- "column_break_5",
- "volunteer_type",
- "email",
- "image",
- "address_contacts",
- "address_html",
- "column_break_9",
- "contact_html",
- "volunteer_availability_and_skills_details",
- "availability",
- "availability_timeslot",
- "column_break_12",
- "volunteer_skills",
- "section_break_15",
- "note"
- ],
- "fields": [
- {
- "fieldname": "volunteer_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Volunteer Name",
- "reqd": 1
- },
- {
- "fieldname": "column_break_5",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "volunteer_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Volunteer Type",
- "options": "Volunteer Type",
- "reqd": 1
- },
- {
- "fieldname": "email",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Email",
- "reqd": 1,
- "unique": 1
- },
- {
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "label": "Image",
- "no_copy": 1,
- "print_hide": 1
- },
- {
- "depends_on": "eval:!doc.__islocal;",
- "fieldname": "address_contacts",
- "fieldtype": "Section Break",
- "label": "Address and Contact",
- "options": "fa fa-map-marker"
- },
- {
- "fieldname": "address_html",
- "fieldtype": "HTML",
- "label": "Address HTML"
- },
- {
- "fieldname": "column_break_9",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "contact_html",
- "fieldtype": "HTML",
- "label": "Contact HTML"
- },
- {
- "fieldname": "volunteer_availability_and_skills_details",
- "fieldtype": "Section Break",
- "label": "Availability and Skills"
- },
- {
- "fieldname": "availability",
- "fieldtype": "Select",
- "label": "Availability",
- "options": "\nWeekly\nWeekdays\nWeekends"
- },
- {
- "fieldname": "availability_timeslot",
- "fieldtype": "Select",
- "label": "Availability Timeslot",
- "options": "\nMorning\nAfternoon\nEvening\nAnytime"
- },
- {
- "fieldname": "column_break_12",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "volunteer_skills",
- "fieldtype": "Table",
- "label": "Volunteer Skills",
- "options": "Volunteer Skill"
- },
- {
- "fieldname": "section_break_15",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "note",
- "fieldtype": "Long Text",
- "label": "Note"
- }
- ],
- "image_field": "image",
- "links": [],
- "modified": "2020-09-16 23:45:15.595952",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Volunteer",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "restrict_to_domain": "Non Profit",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "volunteer_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.py b/erpnext/non_profit/doctype/volunteer/volunteer.py
deleted file mode 100644
index b44d67dae3..0000000000
--- a/erpnext/non_profit/doctype/volunteer/volunteer.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.model.document import Document
-
-
-class Volunteer(Document):
- def onload(self):
- """Load address and contacts in `__onload`"""
- load_address_and_contact(self)
diff --git a/erpnext/non_profit/doctype/volunteer_skill/__init__.py b/erpnext/non_profit/doctype/volunteer_skill/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json
deleted file mode 100644
index 7d210aa7bd..0000000000
--- a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-09-20 15:26:26.453435",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "volunteer_skill",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Volunteer Skill",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-12-06 11:54:14.396354",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Volunteer Skill",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py
deleted file mode 100644
index fe7251876d..0000000000
--- a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class VolunteerSkill(Document):
- pass
diff --git a/erpnext/non_profit/doctype/volunteer_type/__init__.py b/erpnext/non_profit/doctype/volunteer_type/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py
deleted file mode 100644
index cef27c83a5..0000000000
--- a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestVolunteerType(unittest.TestCase):
- pass
diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js
deleted file mode 100644
index 5c17505be9..0000000000
--- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Volunteer Type', {
- refresh: function() {
-
- }
-});
diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json
deleted file mode 100644
index 256b25fe91..0000000000
--- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json
+++ /dev/null
@@ -1,94 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "prompt",
- "beta": 0,
- "creation": "2017-09-19 16:13:07.763273",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Amount",
- "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,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-12-06 11:52:08.800425",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Volunteer Type",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Non Profit Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Non Profit",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py
deleted file mode 100644
index 3b1ae1a88e..0000000000
--- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class VolunteerType(Document):
- pass
diff --git a/erpnext/non_profit/report/__init__.py b/erpnext/non_profit/report/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/report/expiring_memberships/__init__.py b/erpnext/non_profit/report/expiring_memberships/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js
deleted file mode 100644
index be3a2438fc..0000000000
--- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-/* eslint-disable */
-
-frappe.query_reports["Expiring Memberships"] = {
- "filters": [
- {
- "fieldname": "fiscal_year",
- "label": __("Fiscal Year"),
- "fieldtype": "Link",
- "options": "Fiscal Year",
- "default": frappe.defaults.get_user_default("fiscal_year"),
- "reqd": 1
- },
- {
- "fieldname":"month",
- "label": __("Month"),
- "fieldtype": "Select",
- "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
- "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
- "Dec"][frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth()],
- }
- ]
-}
diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json
deleted file mode 100644
index c311057201..0000000000
--- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "add_total_row": 0,
- "apply_user_permissions": 1,
- "creation": "2018-05-24 11:44:08.942809",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Report",
- "idx": 0,
- "is_standard": "Yes",
- "letter_head": "ERPNext Foundation",
- "modified": "2018-05-24 11:44:08.942809",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Expiring Memberships",
- "owner": "Administrator",
- "ref_doctype": "Membership",
- "report_name": "Expiring Memberships",
- "report_type": "Script Report",
- "roles": [
- {
- "role": "Non Profit Manager"
- },
- {
- "role": "Non Profit Member"
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py
deleted file mode 100644
index 3ddbfdc3b0..0000000000
--- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-
-
-def execute(filters=None):
- columns = get_columns(filters)
- data = get_data(filters)
- return columns, data
-
-def get_columns(filters):
- return [
- _("Membership Type") + ":Link/Membership Type:100", _("Membership ID") + ":Link/Membership:140",
- _("Member ID") + ":Link/Member:140", _("Member Name") + ":Data:140", _("Email") + ":Data:140",
- _("Expiring On") + ":Date:120"
- ]
-
-def get_data(filters):
-
- filters["month"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].index(filters.month) + 1
-
- return frappe.db.sql("""
- select ms.membership_type,ms.name,m.name,m.member_name,m.email,ms.max_membership_date
- from `tabMember` m
- inner join (select name,membership_type,max(to_date) as max_membership_date,member
- from `tabMembership`
- where paid = 1
- group by member
- order by max_membership_date asc) ms
- on m.name = ms.member
- where month(max_membership_date) = %(month)s and year(max_membership_date) = %(year)s """,{'month': filters.get('month'),'year':filters.get('fiscal_year')})
diff --git a/erpnext/non_profit/utils.py b/erpnext/non_profit/utils.py
deleted file mode 100644
index 47ea5f5783..0000000000
--- a/erpnext/non_profit/utils.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import frappe
-
-
-def get_company():
- company = frappe.defaults.get_defaults().company
- if company:
- return company
- else:
- company = frappe.get_list("Company", limit=1)
- if company:
- return company[0].name
- return None
diff --git a/erpnext/non_profit/web_form/__init__.py b/erpnext/non_profit/web_form/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/web_form/certification_application/__init__.py b/erpnext/non_profit/web_form/certification_application/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.js b/erpnext/non_profit/web_form/certification_application/certification_application.js
deleted file mode 100644
index 8b455edafa..0000000000
--- a/erpnext/non_profit/web_form/certification_application/certification_application.js
+++ /dev/null
@@ -1,16 +0,0 @@
-frappe.ready(function() {
- // bind events here
- $(".page-header-actions-block .btn-primary, .page-header-actions-block .btn-default").addClass('hidden');
- $(".text-right .btn-primary").addClass('hidden');
-
- if (frappe.utils.get_url_arg('name')) {
- $('.page-content .btn-form-submit').addClass('hidden');
- } else {
- user_name = frappe.full_name
- user_email_id = frappe.session.user
- $('[data-fieldname="currency"]').val("INR");
- $('[data-fieldname="name_of_applicant"]').val(user_name);
- $('[data-fieldname="email"]').val(user_email_id);
- $('[data-fieldname="amount"]').val(20000);
- }
-})
diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.json b/erpnext/non_profit/web_form/certification_application/certification_application.json
deleted file mode 100644
index 5fda978fba..0000000000
--- a/erpnext/non_profit/web_form/certification_application/certification_application.json
+++ /dev/null
@@ -1,79 +0,0 @@
-{
- "accept_payment": 1,
- "allow_comments": 0,
- "allow_delete": 0,
- "allow_edit": 0,
- "allow_incomplete": 0,
- "allow_multiple": 1,
- "allow_print": 0,
- "amount": 0.0,
- "amount_based_on_field": 1,
- "amount_field": "amount",
- "creation": "2018-06-08 16:24:05.805225",
- "doc_type": "Certification Application",
- "docstatus": 0,
- "doctype": "Web Form",
- "idx": 0,
- "introduction_text": "",
- "is_standard": 1,
- "login_required": 1,
- "max_attachment_size": 0,
- "modified": "2018-06-11 16:11:14.544987",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "certification-application",
- "owner": "Administrator",
- "payment_button_help": "Pay for your certification using RazorPay",
- "payment_button_label": "Pay Now",
- "payment_gateway": "Razorpay",
- "published": 1,
- "route": "certification-application",
- "show_sidebar": 1,
- "sidebar_items": [],
- "success_url": "/certification-application",
- "title": "Certification Application",
- "web_form_fields": [
- {
- "fieldname": "name_of_applicant",
- "fieldtype": "Data",
- "hidden": 0,
- "label": "Name of Applicant",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 0
- },
- {
- "fieldname": "email",
- "fieldtype": "Link",
- "hidden": 0,
- "label": "Email",
- "max_length": 0,
- "max_value": 0,
- "options": "User",
- "read_only": 1,
- "reqd": 1
- },
- {
- "fieldname": "currency",
- "fieldtype": "Select",
- "hidden": 0,
- "label": "Currency",
- "max_length": 0,
- "max_value": 0,
- "options": "USD\nINR",
- "read_only": 1,
- "reqd": 0
- },
- {
- "fieldname": "amount",
- "fieldtype": "Float",
- "hidden": 0,
- "label": "Amount",
- "max_length": 0,
- "max_value": 0,
- "read_only": 1,
- "reqd": 0
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.py b/erpnext/non_profit/web_form/certification_application/certification_application.py
deleted file mode 100644
index 02e3e93333..0000000000
--- a/erpnext/non_profit/web_form/certification_application/certification_application.py
+++ /dev/null
@@ -1,3 +0,0 @@
-def get_context(context):
- # do your magic here
- pass
diff --git a/erpnext/non_profit/web_form/certification_application_usd/__init__.py b/erpnext/non_profit/web_form/certification_application_usd/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js
deleted file mode 100644
index 005d1dd6c1..0000000000
--- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js
+++ /dev/null
@@ -1,16 +0,0 @@
-frappe.ready(function() {
- // bind events here
- $(".page-header-actions-block .btn-primary, .page-header-actions-block .btn-default").addClass('hidden');
- $(".text-right .btn-primary").addClass('hidden');
-
- if (frappe.utils.get_url_arg('name')) {
- $('.page-content .btn-form-submit').addClass('hidden');
- } else {
- user_name = frappe.full_name
- user_email_id = frappe.session.user
- $('[data-fieldname="currency"]').val("USD");
- $('[data-fieldname="name_of_applicant"]').val(user_name);
- $('[data-fieldname="email"]').val(user_email_id);
- $('[data-fieldname="amount"]').val(300);
- }
-})
diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json
deleted file mode 100644
index 266109f580..0000000000
--- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json
+++ /dev/null
@@ -1,80 +0,0 @@
-{
- "accept_payment": 1,
- "allow_comments": 0,
- "allow_delete": 0,
- "allow_edit": 0,
- "allow_incomplete": 0,
- "allow_multiple": 1,
- "allow_print": 0,
- "amount": 0.0,
- "amount_based_on_field": 1,
- "amount_field": "amount",
- "creation": "2018-06-13 09:22:48.262441",
- "currency": "USD",
- "doc_type": "Certification Application",
- "docstatus": 0,
- "doctype": "Web Form",
- "idx": 0,
- "introduction_text": "",
- "is_standard": 1,
- "login_required": 1,
- "max_attachment_size": 0,
- "modified": "2018-06-13 09:26:35.502064",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "certification-application-usd",
- "owner": "Administrator",
- "payment_button_help": "Pay for your certification using PayPal",
- "payment_button_label": "Pay Now",
- "payment_gateway": "PayPal",
- "published": 1,
- "route": "certification-application-usd",
- "show_sidebar": 1,
- "sidebar_items": [],
- "success_url": "/certification-application-usd",
- "title": "Certification Application USD",
- "web_form_fields": [
- {
- "fieldname": "name_of_applicant",
- "fieldtype": "Data",
- "hidden": 0,
- "label": "Name of Applicant",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 0
- },
- {
- "fieldname": "email",
- "fieldtype": "Link",
- "hidden": 0,
- "label": "Email",
- "max_length": 0,
- "max_value": 0,
- "options": "User",
- "read_only": 1,
- "reqd": 1
- },
- {
- "fieldname": "currency",
- "fieldtype": "Select",
- "hidden": 0,
- "label": "Currency",
- "max_length": 0,
- "max_value": 0,
- "options": "USD\nINR",
- "read_only": 1,
- "reqd": 0
- },
- {
- "fieldname": "amount",
- "fieldtype": "Float",
- "hidden": 0,
- "label": "Amount",
- "max_length": 0,
- "max_value": 0,
- "read_only": 1,
- "reqd": 0
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py
deleted file mode 100644
index 02e3e93333..0000000000
--- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py
+++ /dev/null
@@ -1,3 +0,0 @@
-def get_context(context):
- # do your magic here
- pass
diff --git a/erpnext/non_profit/web_form/grant_application/__init__.py b/erpnext/non_profit/web_form/grant_application/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.js b/erpnext/non_profit/web_form/grant_application/grant_application.js
deleted file mode 100644
index f09e540919..0000000000
--- a/erpnext/non_profit/web_form/grant_application/grant_application.js
+++ /dev/null
@@ -1,3 +0,0 @@
-frappe.ready(function() {
- // bind events here
-});
diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.json b/erpnext/non_profit/web_form/grant_application/grant_application.json
deleted file mode 100644
index 73c9445500..0000000000
--- a/erpnext/non_profit/web_form/grant_application/grant_application.json
+++ /dev/null
@@ -1,108 +0,0 @@
-{
- "accept_payment": 0,
- "allow_comments": 0,
- "allow_delete": 1,
- "allow_edit": 1,
- "allow_incomplete": 0,
- "allow_multiple": 1,
- "allow_print": 0,
- "amount": 0.0,
- "amount_based_on_field": 0,
- "creation": "2017-10-30 15:57:10.825188",
- "currency": "INR",
- "doc_type": "Grant Application",
- "docstatus": 0,
- "doctype": "Web Form",
- "idx": 0,
- "introduction_text": "Share as many details as you can to get quick response from organization",
- "is_standard": 1,
- "login_required": 1,
- "max_attachment_size": 0,
- "modified": "2017-12-06 12:32:16.893289",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "grant-application",
- "owner": "Administrator",
- "payment_button_label": "Buy Now",
- "published": 1,
- "route": "my-grant",
- "show_sidebar": 1,
- "sidebar_items": [],
- "success_url": "/grant-application",
- "title": "Grant Application",
- "web_form_fields": [
- {
- "fieldname": "applicant_type",
- "fieldtype": "Select",
- "hidden": 0,
- "label": "Applicant Type",
- "max_length": 0,
- "max_value": 0,
- "options": "Individual\nOrganization",
- "read_only": 0,
- "reqd": 1
- },
- {
- "fieldname": "applicant_name",
- "fieldtype": "Data",
- "hidden": 0,
- "label": "Name",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 1
- },
- {
- "fieldname": "email",
- "fieldtype": "Data",
- "hidden": 0,
- "label": "Email Address",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 1
- },
- {
- "description": "",
- "fieldname": "grant_description",
- "fieldtype": "Text",
- "hidden": 0,
- "label": "Please outline your current situation and why you are applying for a grant?",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 1
- },
- {
- "fieldname": "amount",
- "fieldtype": "Float",
- "hidden": 0,
- "label": "Requested Amount",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 0
- },
- {
- "fieldname": "has_any_past_grant_record",
- "fieldtype": "Check",
- "hidden": 0,
- "label": "Have you received any grant from us before?",
- "max_length": 0,
- "max_value": 0,
- "options": "",
- "read_only": 0,
- "reqd": 0
- },
- {
- "fieldname": "published",
- "fieldtype": "Check",
- "hidden": 0,
- "label": "Show on Website",
- "max_length": 0,
- "max_value": 0,
- "read_only": 0,
- "reqd": 0
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.py b/erpnext/non_profit/web_form/grant_application/grant_application.py
deleted file mode 100644
index 3dfb381f65..0000000000
--- a/erpnext/non_profit/web_form/grant_application/grant_application.py
+++ /dev/null
@@ -1,4 +0,0 @@
-def get_context(context):
- context.no_cache = True
- context.parents = [dict(label='View All ',
- route='grant-application', title='View All')]
diff --git a/erpnext/non_profit/workspace/non_profit/non_profit.json b/erpnext/non_profit/workspace/non_profit/non_profit.json
deleted file mode 100644
index ba2f919d01..0000000000
--- a/erpnext/non_profit/workspace/non_profit/non_profit.json
+++ /dev/null
@@ -1,272 +0,0 @@
-{
- "charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Member\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Non Profit Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Membership\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Chapter\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Chapter Member\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Loan Management\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Grant Application\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Membership\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Volunteer\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Chapter\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Donation\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Tax Exemption Certification (India)\", \"col\": 4}}]",
- "creation": "2020-03-02 17:23:47.811421",
- "docstatus": 0,
- "doctype": "Workspace",
- "for_user": "",
- "hide_custom": 0,
- "icon": "non-profit",
- "idx": 0,
- "label": "Non Profit",
- "links": [
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Management",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Type",
- "link_count": 0,
- "link_to": "Loan Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Application",
- "link_count": 0,
- "link_to": "Loan Application",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan",
- "link_count": 0,
- "link_to": "Loan",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Grant Application",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Grant Application",
- "link_count": 0,
- "link_to": "Grant Application",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Member",
- "link_count": 0,
- "link_to": "Member",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership",
- "link_count": 0,
- "link_to": "Membership",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership Type",
- "link_count": 0,
- "link_to": "Membership Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership Settings",
- "link_count": 0,
- "link_to": "Non Profit Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer",
- "link_count": 0,
- "link_to": "Volunteer",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer Type",
- "link_count": 0,
- "link_to": "Volunteer Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Chapter",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Chapter",
- "link_count": 0,
- "link_to": "Chapter",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donation",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donor",
- "link_count": 0,
- "link_to": "Donor",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donor Type",
- "link_count": 0,
- "link_to": "Donor Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donation",
- "link_count": 0,
- "link_to": "Donation",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Tax Exemption Certification (India)",
- "link_count": 0,
- "link_type": "DocType",
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Tax Exemption 80G Certificate",
- "link_count": 0,
- "link_to": "Tax Exemption 80G Certificate",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- }
- ],
- "modified": "2021-08-05 12:16:01.146207",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Non Profit",
- "owner": "Administrator",
- "parent_page": "",
- "public": 1,
- "restrict_to_domain": "Non Profit",
- "roles": [],
- "sequence_id": 18,
- "shortcuts": [
- {
- "label": "Member",
- "link_to": "Member",
- "type": "DocType"
- },
- {
- "label": "Non Profit Settings",
- "link_to": "Non Profit Settings",
- "type": "DocType"
- },
- {
- "label": "Membership",
- "link_to": "Membership",
- "type": "DocType"
- },
- {
- "label": "Chapter",
- "link_to": "Chapter",
- "type": "DocType"
- },
- {
- "label": "Chapter Member",
- "link_to": "Chapter Member",
- "type": "DocType"
- }
- ],
- "title": "Non Profit"
-}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 268db40a8e..970a8f9b5d 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -323,3 +323,5 @@ execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings'
erpnext.patches.v14_0.set_payroll_cost_centers
erpnext.patches.v13_0.agriculture_deprecation_warning
erpnext.patches.v14_0.delete_agriculture_doctypes
+erpnext.patches.v13_0.non_profit_deprecation_warning
+erpnext.patches.v14_0.delete_non_profit_doctypes
diff --git a/erpnext/patches/v13_0/non_profit_deprecation_warning.py b/erpnext/patches/v13_0/non_profit_deprecation_warning.py
new file mode 100644
index 0000000000..c170de5c1c
--- /dev/null
+++ b/erpnext/patches/v13_0/non_profit_deprecation_warning.py
@@ -0,0 +1,10 @@
+import click
+
+
+def execute():
+
+ click.secho(
+ "Non Profit Domain is moved to a separate app and will be removed from ERPNext in version-14.\n"
+ "When upgrading to ERPNext version-14, please install the app to continue using the Agriculture domain: https://github.com/frappe/non_profit",
+ fg="yellow",
+ )
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
new file mode 100644
index 0000000000..3b3dbe4576
--- /dev/null
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -0,0 +1,19 @@
+import frappe
+
+
+def execute():
+ frappe.delete_doc("Module Def", "Non Profit", ignore_missing=True, force=True)
+
+ frappe.delete_doc("Workspace", "Non Profit", ignore_missing=True, force=True)
+
+ reports = frappe.get_all("Report", {"module": "Non Profit", "is_standard": "Yes"}, pluck='name')
+ for report in reports:
+ frappe.delete_doc("Report", report, ignore_missing=True, force=True)
+
+ dashboards = frappe.get_all("Dashboard", {"module": "Non Profit", "is_standard": 1}, pluck='name')
+ for dashboard in dashboards:
+ frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True)
+
+ doctypes = frappe.get_all("DocType", {"module": "Non Profit", "custom": 0}, pluck='name')
+ for doctype in doctypes:
+ frappe.delete_doc("DocType", doctype, ignore_missing=True)
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index c0dcb70b92..fa4e454f33 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -679,14 +679,6 @@ def get_custom_fields():
'insert_after': 'email_id'
}
],
- 'Donor': [
- {
- 'fieldname': 'pan_number',
- 'label': 'PAN Details',
- 'fieldtype': 'Data',
- 'insert_after': 'email'
- }
- ],
'Finance Book': [
{
'fieldname': 'for_income_tax',
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 336b51c0ab..906db561db 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -198,7 +198,6 @@ def install(country=None):
{'doctype': "Party Type", "party_type": "Member", "account_type": "Receivable"},
{'doctype': "Party Type", "party_type": "Shareholder", "account_type": "Payable"},
{'doctype': "Party Type", "party_type": "Student", "account_type": "Receivable"},
- {'doctype': "Party Type", "party_type": "Donor", "account_type": "Receivable"},
{'doctype': "Opportunity Type", "name": _("Sales")},
{'doctype': "Opportunity Type", "name": _("Support")},
From f423de530a4140bfb84e93dbfa0f1140dcaa8e9b Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 20 Jan 2022 11:02:30 +0530
Subject: [PATCH 02/64] refactor: Code cleanup
---
.../doctype/membership/membership.py | 415 ------------------
erpnext/regional/india/setup.py | 8 -
.../operations/install_fixtures.py | 1 -
3 files changed, 424 deletions(-)
delete mode 100644 erpnext/non_profit/doctype/membership/membership.py
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
deleted file mode 100644
index f9b295a223..0000000000
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ /dev/null
@@ -1,415 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import json
-from datetime import datetime
-
-import frappe
-from frappe import _
-from frappe.email import sendmail_to_system_managers
-from frappe.model.document import Document
-from frappe.utils import add_days, add_months, add_years, get_link_to_form, getdate, nowdate
-
-import erpnext
-from erpnext.non_profit.doctype.member.member import create_member
-
-
-class Membership(Document):
- def validate(self):
- if not self.member or not frappe.db.exists("Member", self.member):
- # for web forms
- user_type = frappe.db.get_value("User", frappe.session.user, "user_type")
- if user_type == "Website User":
- self.create_member_from_website_user()
- else:
- frappe.throw(_("Please select a Member"))
-
- self.validate_membership_period()
-
- def create_member_from_website_user(self):
- member_name = frappe.get_value("Member", dict(email_id=frappe.session.user))
-
- if not member_name:
- user = frappe.get_doc("User", frappe.session.user)
- member = frappe.get_doc(dict(
- doctype="Member",
- email_id=frappe.session.user,
- membership_type=self.membership_type,
- member_name=user.get_fullname()
- )).insert(ignore_permissions=True)
- member_name = member.name
-
- if self.get("__islocal"):
- self.member = member_name
-
- def validate_membership_period(self):
- # get last membership (if active)
- last_membership = erpnext.get_last_membership(self.member)
-
- # if person applied for offline membership
- if last_membership and last_membership.name != self.name and not frappe.session.user == "Administrator":
- # if last membership does not expire in 30 days, then do not allow to renew
- if getdate(add_days(last_membership.to_date, -30)) > getdate(nowdate()) :
- frappe.throw(_("You can only renew if your membership expires within 30 days"))
-
- self.from_date = add_days(last_membership.to_date, 1)
- elif frappe.session.user == "Administrator":
- self.from_date = self.from_date
- else:
- self.from_date = nowdate()
-
- if frappe.db.get_single_value("Non Profit Settings", "billing_cycle") == "Yearly":
- self.to_date = add_years(self.from_date, 1)
- else:
- self.to_date = add_months(self.from_date, 1)
-
- def on_payment_authorized(self, status_changed_to=None):
- if status_changed_to not in ("Completed", "Authorized"):
- return
- self.load_from_db()
- self.db_set("paid", 1)
- settings = frappe.get_doc("Non Profit Settings")
- if settings.allow_invoicing and settings.automate_membership_invoicing:
- self.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True)
-
-
- @frappe.whitelist()
- def generate_invoice(self, save=True, with_payment_entry=False):
- if not (self.paid or self.currency or self.amount):
- frappe.throw(_("The payment for this membership is not paid. To generate invoice fill the payment details"))
-
- if self.invoice:
- frappe.throw(_("An invoice is already linked to this document"))
-
- member = frappe.get_doc("Member", self.member)
- if not member.customer:
- frappe.throw(_("No customer linked to member {0}").format(frappe.bold(self.member)))
-
- plan = frappe.get_doc("Membership Type", self.membership_type)
- settings = frappe.get_doc("Non Profit Settings")
- self.validate_membership_type_and_settings(plan, settings)
-
- invoice = make_invoice(self, member, plan, settings)
- self.reload()
- self.invoice = invoice.name
-
- if with_payment_entry:
- self.make_payment_entry(settings, invoice)
-
- if save:
- self.save()
-
- return invoice
-
- def validate_membership_type_and_settings(self, plan, settings):
- settings_link = get_link_to_form("Membership Type", self.membership_type)
-
- if not settings.membership_debit_account:
- frappe.throw(_("You need to set Debit Account in {0}").format(settings_link))
-
- if not settings.company:
- frappe.throw(_("You need to set Default Company for invoicing in {0}").format(settings_link))
-
- if not plan.linked_item:
- frappe.throw(_("Please set a Linked Item for the Membership Type {0}").format(
- get_link_to_form("Membership Type", self.membership_type)))
-
- def make_payment_entry(self, settings, invoice):
- if not settings.membership_payment_account:
- frappe.throw(_("You need to set Payment Account for Membership in {0}").format(
- get_link_to_form("Non Profit Settings", "Non Profit Settings")))
-
- from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
- frappe.flags.ignore_account_permission = True
- pe = get_payment_entry(dt="Sales Invoice", dn=invoice.name, bank_amount=invoice.grand_total)
- frappe.flags.ignore_account_permission=False
- pe.paid_to = settings.membership_payment_account
- pe.reference_no = self.name
- pe.reference_date = getdate()
- pe.flags.ignore_mandatory = True
- pe.save()
- pe.submit()
-
- @frappe.whitelist()
- def send_acknowlement(self):
- settings = frappe.get_doc("Non Profit Settings")
- if not settings.send_email:
- frappe.throw(_("You need to enable Send Acknowledge Email in {0}").format(
- get_link_to_form("Non Profit Settings", "Non Profit Settings")))
-
- member = frappe.get_doc("Member", self.member)
- if not member.email_id:
- frappe.throw(_("Email address of member {0} is missing").format(frappe.utils.get_link_to_form("Member", self.member)))
-
- plan = frappe.get_doc("Membership Type", self.membership_type)
- email = member.email_id
- attachments = [frappe.attach_print("Membership", self.name, print_format=settings.membership_print_format)]
-
- if self.invoice and settings.send_invoice:
- attachments.append(frappe.attach_print("Sales Invoice", self.invoice, print_format=settings.inv_print_format))
-
- email_template = frappe.get_doc("Email Template", settings.email_template)
- context = { "doc": self, "member": member}
-
- email_args = {
- "recipients": [email],
- "message": frappe.render_template(email_template.get("response"), context),
- "subject": frappe.render_template(email_template.get("subject"), context),
- "attachments": attachments,
- "reference_doctype": self.doctype,
- "reference_name": self.name
- }
-
- if not frappe.flags.in_test:
- frappe.enqueue(method=frappe.sendmail, queue="short", timeout=300, is_async=True, **email_args)
- else:
- frappe.sendmail(**email_args)
-
- def generate_and_send_invoice(self):
- self.generate_invoice(save=False)
- self.send_acknowlement()
-
-
-def make_invoice(membership, member, plan, settings):
- invoice = frappe.get_doc({
- "doctype": "Sales Invoice",
- "customer": member.customer,
- "debit_to": settings.membership_debit_account,
- "currency": membership.currency,
- "company": settings.company,
- "is_pos": 0,
- "items": [
- {
- "item_code": plan.linked_item,
- "rate": membership.amount,
- "qty": 1
- }
- ]
- })
- invoice.set_missing_values()
- invoice.insert()
- invoice.submit()
-
- frappe.msgprint(_("Sales Invoice created successfully"))
-
- return invoice
-
-
-def get_member_based_on_subscription(subscription_id, email=None, customer_id=None):
- filters = {"subscription_id": subscription_id}
- if email:
- filters.update({"email_id": email})
- if customer_id:
- filters.update({"customer_id": customer_id})
-
- members = frappe.get_all("Member", filters=filters, order_by="creation desc")
-
- try:
- return frappe.get_doc("Member", members[0]["name"])
- except Exception:
- return None
-
-
-def verify_signature(data, endpoint="Membership"):
- signature = frappe.request.headers.get("X-Razorpay-Signature")
-
- settings = frappe.get_doc("Non Profit Settings")
- key = settings.get_webhook_secret(endpoint)
-
- controller = frappe.get_doc("Razorpay Settings")
-
- controller.verify_signature(data, signature, key)
- frappe.set_user(settings.creation_user)
-
-
-@frappe.whitelist(allow_guest=True)
-def trigger_razorpay_subscription(*args, **kwargs):
- data = frappe.request.get_data(as_text=True)
- data = process_request_data(data)
-
- subscription = data.payload.get("subscription", {}).get("entity", {})
- subscription = frappe._dict(subscription)
-
- payment = data.payload.get("payment", {}).get("entity", {})
- payment = frappe._dict(payment)
-
- try:
- if not data.event == "subscription.charged":
- return
-
- member = get_member_based_on_subscription(subscription.id, payment.email)
- if not member:
- member = create_member(frappe._dict({
- "fullname": payment.email,
- "email": payment.email,
- "plan_id": get_plan_from_razorpay_id(subscription.plan_id)
- }))
-
- member.subscription_id = subscription.id
- member.customer_id = payment.customer_id
-
- if subscription.get("notes"):
- member = get_additional_notes(member, subscription)
-
- company = get_company_for_memberships()
- # Update Membership
- membership = frappe.new_doc("Membership")
- membership.update({
- "company": company,
- "member": member.name,
- "membership_status": "Current",
- "membership_type": member.membership_type,
- "currency": "INR",
- "paid": 1,
- "payment_id": payment.id,
- "from_date": datetime.fromtimestamp(subscription.current_start),
- "to_date": datetime.fromtimestamp(subscription.current_end),
- "amount": payment.amount / 100 # Convert to rupees from paise
- })
- membership.flags.ignore_mandatory = True
- membership.insert()
-
- # Update membership values
- member.subscription_start = datetime.fromtimestamp(subscription.start_at)
- member.subscription_end = datetime.fromtimestamp(subscription.end_at)
- member.subscription_status = "Active"
- member.flags.ignore_mandatory = True
- member.save()
-
- settings = frappe.get_doc("Non Profit Settings")
- if settings.allow_invoicing and settings.automate_membership_invoicing:
- membership.reload()
- membership.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True)
-
- except Exception as e:
- message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), _("Payment ID"), payment.id)
- log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
- notify_failure(log)
- return {"status": "Failed", "reason": e}
-
- return {"status": "Success"}
-
-
-@frappe.whitelist(allow_guest=True)
-def update_halted_razorpay_subscription(*args, **kwargs):
- """
- When all retries have been exhausted, Razorpay moves the subscription to the halted state.
- The customer has to manually retry the charge or change the card linked to the subscription,
- for the subscription to move back to the active state.
- """
- if frappe.request:
- data = frappe.request.get_data(as_text=True)
- data = process_request_data(data)
- elif frappe.flags.in_test:
- data = kwargs.get("data")
- data = frappe._dict(data)
- else:
- return
-
- if not data.event == "subscription.halted":
- return
-
- subscription = data.payload.get("subscription", {}).get("entity", {})
- subscription = frappe._dict(subscription)
-
- try:
- member = get_member_based_on_subscription(subscription.id, customer_id=subscription.customer_id)
- if not member:
- frappe.throw(_("Member with Razorpay Subscription ID {0} not found").format(subscription.id))
-
- member.subscription_status = "Halted"
- member.flags.ignore_mandatory = True
- member.save()
-
- if subscription.get("notes"):
- member = get_additional_notes(member, subscription)
-
- except Exception as e:
- message = "{0}\n\n{1}".format(e, frappe.get_traceback())
- log = frappe.log_error(message, _("Error updating halted status for member {0}").format(member.name))
- notify_failure(log)
- return {"status": "Failed", "reason": e}
-
- return {"status": "Success"}
-
-
-def process_request_data(data):
- try:
- verify_signature(data)
- except Exception as e:
- log = frappe.log_error(e, "Membership Webhook Verification Error")
- notify_failure(log)
- return {"status": "Failed", "reason": e}
-
- if isinstance(data, str):
- data = json.loads(data)
- data = frappe._dict(data)
-
- return data
-
-
-def get_company_for_memberships():
- company = frappe.db.get_single_value("Non Profit Settings", "company")
- if not company:
- from erpnext.non_profit.utils import get_company
- company = get_company()
- return company
-
-
-def get_additional_notes(member, subscription):
- if type(subscription.notes) == dict:
- for k, v in subscription.notes.items():
- notes = "\n".join("{}: {}".format(k, v))
-
- # extract member name from notes
- if "name" in k.lower():
- member.update({
- "member_name": subscription.notes.get(k)
- })
-
- # extract pan number from notes
- if "pan" in k.lower():
- member.update({
- "pan_number": subscription.notes.get(k)
- })
-
- member.add_comment("Comment", notes)
-
- elif type(subscription.notes) == str:
- member.add_comment("Comment", subscription.notes)
-
- return member
-
-
-def notify_failure(log):
- try:
- content = """
- Dear System Manager,
- Razorpay webhook for creating renewing membership subscription failed due to some reason.
- Please check the following error log linked below
- Error Log: {0}
- Regards, Administrator
- """.format(get_link_to_form("Error Log", log.name))
-
- sendmail_to_system_managers("[Important] [ERPNext] Razorpay membership webhook failed , please check.", content)
- except Exception:
- pass
-
-
-def get_plan_from_razorpay_id(plan_id):
- plan = frappe.get_all("Membership Type", filters={"razorpay_plan_id": plan_id}, order_by="creation desc")
-
- try:
- return plan[0]["name"]
- except Exception:
- return None
-
-
-def set_expired_status():
- frappe.db.sql("""
- UPDATE
- `tabMembership` SET `membership_status` = 'Expired'
- WHERE
- `membership_status` not in ('Cancelled') AND `to_date` < %s
- """, (nowdate()))
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index fa4e454f33..ecd9294342 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -671,14 +671,6 @@ def get_custom_fields():
'mandatory_depends_on': 'eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)'
}
],
- 'Member': [
- {
- 'fieldname': 'pan_number',
- 'label': 'PAN Details',
- 'fieldtype': 'Data',
- 'insert_after': 'email_id'
- }
- ],
'Finance Book': [
{
'fieldname': 'for_income_tax',
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 906db561db..bf3525998c 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -195,7 +195,6 @@ def install(country=None):
{'doctype': "Party Type", "party_type": "Customer", "account_type": "Receivable"},
{'doctype': "Party Type", "party_type": "Supplier", "account_type": "Payable"},
{'doctype': "Party Type", "party_type": "Employee", "account_type": "Payable"},
- {'doctype': "Party Type", "party_type": "Member", "account_type": "Receivable"},
{'doctype': "Party Type", "party_type": "Shareholder", "account_type": "Payable"},
{'doctype': "Party Type", "party_type": "Student", "account_type": "Receivable"},
From 4bdf6248aae8140bd3c46846044d9dfe97fcacc6 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Mon, 24 Jan 2022 11:06:11 +0530
Subject: [PATCH 03/64] refactor: Remove regional setup for non-profit
---
.../tax_exemption_80g_certificate/__init__.py | 0
.../tax_exemption_80g_certificate.js | 67 ----
.../tax_exemption_80g_certificate.json | 297 ------------------
.../tax_exemption_80g_certificate.py | 104 ------
.../test_tax_exemption_80g_certificate.py | 106 -------
.../__init__.py | 0
.../tax_exemption_80g_certificate_detail.json | 66 ----
.../tax_exemption_80g_certificate_detail.py | 10 -
8 files changed, 650 deletions(-)
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json
delete mode 100644 erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js
deleted file mode 100644
index 54cde9c0cf..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Tax Exemption 80G Certificate', {
- refresh: function(frm) {
- if (frm.doc.donor) {
- frm.set_query('donation', function() {
- return {
- filters: {
- docstatus: 1,
- donor: frm.doc.donor
- }
- };
- });
- }
- },
-
- recipient: function(frm) {
- if (frm.doc.recipient === 'Donor') {
- frm.set_value({
- 'member': '',
- 'member_name': '',
- 'member_email': '',
- 'member_pan_number': '',
- 'fiscal_year': '',
- 'total': 0,
- 'payments': []
- });
- } else {
- frm.set_value({
- 'donor': '',
- 'donor_name': '',
- 'donor_email': '',
- 'donor_pan_number': '',
- 'donation': '',
- 'date_of_donation': '',
- 'amount': 0,
- 'mode_of_payment': '',
- 'razorpay_payment_id': ''
- });
- }
- },
-
- get_payments: function(frm) {
- frm.call({
- doc: frm.doc,
- method: 'get_payments',
- freeze: true
- });
- },
-
- company: function(frm) {
- if ((frm.doc.member || frm.doc.donor) && frm.doc.company) {
- frm.call({
- doc: frm.doc,
- method: 'set_company_address',
- freeze: true
- });
- }
- },
-
- donation: function(frm) {
- if (frm.doc.recipient === 'Donor' && !frm.doc.donor) {
- frappe.msgprint(__('Please select donor first'));
- }
- }
-});
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json
deleted file mode 100644
index 9eee722f42..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json
+++ /dev/null
@@ -1,297 +0,0 @@
-{
- "actions": [],
- "autoname": "naming_series:",
- "creation": "2021-02-15 12:37:21.577042",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "naming_series",
- "recipient",
- "member",
- "member_name",
- "member_email",
- "member_pan_number",
- "donor",
- "donor_name",
- "donor_email",
- "donor_pan_number",
- "column_break_4",
- "date",
- "fiscal_year",
- "section_break_11",
- "company",
- "company_address",
- "company_address_display",
- "column_break_14",
- "company_pan_number",
- "company_80g_number",
- "company_80g_wef",
- "title",
- "section_break_6",
- "get_payments",
- "payments",
- "total",
- "donation_details_section",
- "donation",
- "date_of_donation",
- "amount",
- "column_break_27",
- "mode_of_payment",
- "razorpay_payment_id"
- ],
- "fields": [
- {
- "fieldname": "recipient",
- "fieldtype": "Select",
- "in_list_view": 1,
- "label": "Certificate Recipient",
- "options": "Member\nDonor",
- "reqd": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fieldname": "member",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Member",
- "mandatory_depends_on": "eval:doc.recipient === \"Member\";",
- "options": "Member"
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fetch_from": "member.member_name",
- "fieldname": "member_name",
- "fieldtype": "Data",
- "label": "Member Name",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Donor\";",
- "fieldname": "donor",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Donor",
- "mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
- "options": "Donor"
- },
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "date",
- "fieldtype": "Date",
- "label": "Date",
- "reqd": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fieldname": "section_break_6",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "payments",
- "fieldtype": "Table",
- "label": "Payments",
- "options": "Tax Exemption 80G Certificate Detail"
- },
- {
- "fieldname": "total",
- "fieldtype": "Currency",
- "in_list_view": 1,
- "label": "Total",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fieldname": "fiscal_year",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Fiscal Year",
- "options": "Fiscal Year"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "fieldname": "get_payments",
- "fieldtype": "Button",
- "label": "Get Memberships"
- },
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Naming Series",
- "options": "NPO-80G-.YYYY.-"
- },
- {
- "fieldname": "section_break_11",
- "fieldtype": "Section Break",
- "label": "Company Details"
- },
- {
- "fieldname": "company_address",
- "fieldtype": "Link",
- "label": "Company Address",
- "options": "Address"
- },
- {
- "fieldname": "column_break_14",
- "fieldtype": "Column Break"
- },
- {
- "fetch_from": "company.pan_details",
- "fieldname": "company_pan_number",
- "fieldtype": "Data",
- "label": "PAN Number",
- "read_only": 1
- },
- {
- "fieldname": "company_address_display",
- "fieldtype": "Small Text",
- "hidden": 1,
- "label": "Company Address Display",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fetch_from": "company.company_80g_number",
- "fieldname": "company_80g_number",
- "fieldtype": "Data",
- "label": "80G Number",
- "read_only": 1
- },
- {
- "fetch_from": "company.with_effect_from",
- "fieldname": "company_80g_wef",
- "fieldtype": "Date",
- "label": "80G With Effect From",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Donor\";",
- "fieldname": "donation_details_section",
- "fieldtype": "Section Break",
- "label": "Donation Details"
- },
- {
- "fieldname": "donation",
- "fieldtype": "Link",
- "label": "Donation",
- "mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
- "options": "Donation"
- },
- {
- "fetch_from": "donation.amount",
- "fieldname": "amount",
- "fieldtype": "Currency",
- "label": "Amount",
- "read_only": 1
- },
- {
- "fetch_from": "donation.mode_of_payment",
- "fieldname": "mode_of_payment",
- "fieldtype": "Link",
- "label": "Mode of Payment",
- "options": "Mode of Payment",
- "read_only": 1
- },
- {
- "fetch_from": "donation.razorpay_payment_id",
- "fieldname": "razorpay_payment_id",
- "fieldtype": "Data",
- "label": "RazorPay Payment ID",
- "read_only": 1
- },
- {
- "fetch_from": "donation.date",
- "fieldname": "date_of_donation",
- "fieldtype": "Date",
- "label": "Date of Donation",
- "read_only": 1
- },
- {
- "fieldname": "column_break_27",
- "fieldtype": "Column Break"
- },
- {
- "depends_on": "eval:doc.recipient === \"Donor\";",
- "fetch_from": "donor.donor_name",
- "fieldname": "donor_name",
- "fieldtype": "Data",
- "label": "Donor Name",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Donor\";",
- "fetch_from": "donor.email",
- "fieldname": "donor_email",
- "fieldtype": "Data",
- "label": "Email",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fetch_from": "member.email_id",
- "fieldname": "member_email",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Email",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Member\";",
- "fetch_from": "member.pan_number",
- "fieldname": "member_pan_number",
- "fieldtype": "Data",
- "label": "PAN Details",
- "read_only": 1
- },
- {
- "depends_on": "eval:doc.recipient === \"Donor\";",
- "fetch_from": "donor.pan_number",
- "fieldname": "donor_pan_number",
- "fieldtype": "Data",
- "label": "PAN Details",
- "read_only": 1
- },
- {
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Title",
- "print_hide": 1
- }
- ],
- "index_web_pages_for_search": 1,
- "links": [],
- "modified": "2021-02-22 00:03:34.215633",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "Tax Exemption 80G Certificate",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
- "search_fields": "member, member_name",
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "title",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py
deleted file mode 100644
index 0f0897841b..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.contacts.doctype.address.address import get_company_address
-from frappe.model.document import Document
-from frappe.utils import flt, get_link_to_form, getdate
-
-from erpnext.accounts.utils import get_fiscal_year
-
-
-class TaxExemption80GCertificate(Document):
- def validate(self):
- self.validate_date()
- self.validate_duplicates()
- self.validate_company_details()
- self.set_company_address()
- self.calculate_total()
- self.set_title()
-
- def validate_date(self):
- if self.recipient == 'Member':
- if getdate(self.date):
- fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
-
- if not (fiscal_year.year_start_date <= getdate(self.date) \
- <= fiscal_year.year_end_date):
- frappe.throw(_('The Certificate Date is not in the Fiscal Year {0}').format(frappe.bold(self.fiscal_year)))
-
- def validate_duplicates(self):
- if self.recipient == 'Donor':
- certificate = frappe.db.exists(self.doctype, {
- 'donation': self.donation,
- 'name': ('!=', self.name)
- })
- if certificate:
- frappe.throw(_('An 80G Certificate {0} already exists for the donation {1}').format(
- get_link_to_form(self.doctype, certificate), frappe.bold(self.donation)
- ), title=_('Duplicate Certificate'))
-
- def validate_company_details(self):
- fields = ['company_80g_number', 'with_effect_from', 'pan_details']
- company_details = frappe.db.get_value('Company', self.company, fields, as_dict=True)
- if not company_details.company_80g_number:
- frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('80G Number'),
- get_link_to_form('Company', self.company)))
-
- if not company_details.pan_details:
- frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('PAN Number'),
- get_link_to_form('Company', self.company)))
-
- @frappe.whitelist()
- def set_company_address(self):
- address = get_company_address(self.company)
- self.company_address = address.company_address
- self.company_address_display = address.company_address_display
-
- def calculate_total(self):
- if self.recipient == 'Donor':
- return
-
- total = 0
- for entry in self.payments:
- total += flt(entry.amount)
- self.total = total
-
- def set_title(self):
- if self.recipient == 'Member':
- self.title = self.member_name
- else:
- self.title = self.donor_name
-
- @frappe.whitelist()
- def get_payments(self):
- if not self.member:
- frappe.throw(_('Please select a Member first.'))
-
- fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
-
- memberships = frappe.db.get_all('Membership', {
- 'member': self.member,
- 'from_date': ['between', (fiscal_year.year_start_date, fiscal_year.year_end_date)],
- 'membership_status': ('!=', 'Cancelled')
- }, ['from_date', 'amount', 'name', 'invoice', 'payment_id'], order_by='from_date')
-
- if not memberships:
- frappe.msgprint(_('No Membership Payments found against the Member {0}').format(self.member))
-
- total = 0
- self.payments = []
-
- for doc in memberships:
- self.append('payments', {
- 'date': doc.from_date,
- 'amount': doc.amount,
- 'invoice_id': doc.invoice,
- 'razorpay_payment_id': doc.payment_id,
- 'membership': doc.name
- })
- total += flt(doc.amount)
-
- self.total = total
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py
deleted file mode 100644
index 6fa3b85d06..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-from frappe.utils import getdate
-
-from erpnext.accounts.utils import get_fiscal_year
-from erpnext.non_profit.doctype.donation.donation import create_donation
-from erpnext.non_profit.doctype.donation.test_donation import (
- create_donor,
- create_donor_type,
- create_mode_of_payment,
-)
-from erpnext.non_profit.doctype.member.member import create_member
-from erpnext.non_profit.doctype.membership.test_membership import make_membership, setup_membership
-
-
-class TestTaxExemption80GCertificate(unittest.TestCase):
- def setUp(self):
- frappe.db.sql('delete from `tabTax Exemption 80G Certificate`')
- frappe.db.sql('delete from `tabMembership`')
- create_donor_type()
- settings = frappe.get_doc('Non Profit Settings')
- settings.company = '_Test Company'
- settings.donation_company = '_Test Company'
- settings.default_donor_type = '_Test Donor'
- settings.creation_user = 'Administrator'
- settings.save()
-
- company = frappe.get_doc('Company', '_Test Company')
- company.pan_details = 'BBBTI3374C'
- company.company_80g_number = 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087'
- company.with_effect_from = getdate()
- company.save()
-
- def test_duplicate_donation_certificate(self):
- donor = create_donor()
- create_mode_of_payment()
- payment = frappe._dict({
- 'amount': 100,
- 'method': 'Debit Card',
- 'id': 'pay_MeXAmsgeKOhq7O'
- })
- donation = create_donation(donor, payment)
-
- args = frappe._dict({
- 'recipient': 'Donor',
- 'donor': donor.name,
- 'donation': donation.name
- })
- certificate = create_80g_certificate(args)
- certificate.insert()
-
- # check company details
- self.assertEqual(certificate.company_pan_number, 'BBBTI3374C')
- self.assertEqual(certificate.company_80g_number, 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087')
-
- # check donation details
- self.assertEqual(certificate.amount, donation.amount)
-
- duplicate_certificate = create_80g_certificate(args)
- # duplicate validation
- self.assertRaises(frappe.ValidationError, duplicate_certificate.insert)
-
- def test_membership_80g_certificate(self):
- plan = setup_membership()
-
- # make test member
- member_doc = create_member(frappe._dict({
- 'fullname': "_Test_Member",
- 'email': "_test_member_erpnext@example.com",
- 'plan_id': plan.name
- }))
- member_doc.make_customer_and_link()
- member = member_doc.name
-
- membership = make_membership(member, { "from_date": getdate() })
- invoice = membership.generate_invoice(save=True)
-
- args = frappe._dict({
- 'recipient': 'Member',
- 'member': member,
- 'fiscal_year': get_fiscal_year(getdate(), as_dict=True).get('name')
- })
- certificate = create_80g_certificate(args)
- certificate.get_payments()
- certificate.insert()
-
- self.assertEqual(len(certificate.payments), 1)
- self.assertEqual(certificate.payments[0].amount, membership.amount)
- self.assertEqual(certificate.payments[0].invoice_id, invoice.name)
-
-
-def create_80g_certificate(args):
- certificate = frappe.get_doc({
- 'doctype': 'Tax Exemption 80G Certificate',
- 'recipient': args.recipient,
- 'date': getdate(),
- 'company': '_Test Company'
- })
-
- certificate.update(args)
-
- return certificate
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json
deleted file mode 100644
index dfa817dd27..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "actions": [],
- "creation": "2021-02-15 12:43:52.754124",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "date",
- "amount",
- "invoice_id",
- "column_break_4",
- "razorpay_payment_id",
- "membership"
- ],
- "fields": [
- {
- "fieldname": "date",
- "fieldtype": "Date",
- "in_list_view": 1,
- "label": "Date",
- "reqd": 1
- },
- {
- "fieldname": "amount",
- "fieldtype": "Currency",
- "in_list_view": 1,
- "label": "Amount",
- "reqd": 1
- },
- {
- "fieldname": "invoice_id",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Invoice ID",
- "options": "Sales Invoice",
- "reqd": 1
- },
- {
- "fieldname": "razorpay_payment_id",
- "fieldtype": "Data",
- "label": "Razorpay Payment ID"
- },
- {
- "fieldname": "membership",
- "fieldtype": "Link",
- "label": "Membership",
- "options": "Membership"
- },
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-02-15 16:35:10.777587",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "Tax Exemption 80G Certificate Detail",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py
deleted file mode 100644
index bb7f07f688..0000000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-# import frappe
-from frappe.model.document import Document
-
-
-class TaxExemption80GCertificateDetail(Document):
- pass
From 16ca81d6a61be4bf7ef2df9ae488c9a49076244c Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 27 Jan 2022 10:05:40 +0530
Subject: [PATCH 04/64] refactor: Remove non-profit code in ERPNext
---
.../doctype/payment_entry/payment_entry.js | 16 +++-----------
.../doctype/payment_entry/payment_entry.py | 22 +------------------
2 files changed, 4 insertions(+), 34 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 3be3925b5a..a9bc0280bc 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -114,8 +114,6 @@ frappe.ui.form.on('Payment Entry', {
var doctypes = ["Expense Claim", "Journal Entry"];
} else if (frm.doc.party_type == "Student") {
var doctypes = ["Fees"];
- } else if (frm.doc.party_type == "Donor") {
- var doctypes = ["Donation"];
} else {
var doctypes = ["Journal Entry"];
}
@@ -144,7 +142,7 @@ frappe.ui.form.on('Payment Entry', {
const child = locals[cdt][cdn];
const filters = {"docstatus": 1, "company": doc.company};
const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
- 'Purchase Order', 'Expense Claim', 'Fees', 'Dunning', 'Donation'];
+ 'Purchase Order', 'Expense Claim', 'Fees', 'Dunning'];
if (in_list(party_type_doctypes, child.reference_doctype)) {
filters[doc.party_type.toLowerCase()] = doc.party;
@@ -747,8 +745,7 @@ frappe.ui.form.on('Payment Entry', {
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
- (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ||
- (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
+ (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
) {
if(total_positive_outstanding > total_negative_outstanding)
if (!frm.doc.paid_amount)
@@ -791,8 +788,7 @@ frappe.ui.form.on('Payment Entry', {
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
- (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ||
- (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
+ (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
) {
if(total_positive_outstanding_including_order > paid_amount) {
var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
@@ -951,12 +947,6 @@ frappe.ui.form.on('Payment Entry', {
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx]));
return false;
}
-
- if (frm.doc.party_type == "Donor" && row.reference_doctype != "Donation") {
- frappe.model.set_value(row.doctype, row.name, "reference_doctype", null);
- frappe.msgprint(__("Row #{0}: Reference Document Type must be Donation", [row.idx]));
- return false;
- }
}
if (row) {
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 02a144d3e7..286052cf3a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -91,7 +91,6 @@ class PaymentEntry(AccountsController):
self.update_expense_claim()
self.update_outstanding_amounts()
self.update_advance_paid()
- self.update_donation()
self.update_payment_schedule()
self.set_status()
@@ -101,7 +100,6 @@ class PaymentEntry(AccountsController):
self.update_expense_claim()
self.update_outstanding_amounts()
self.update_advance_paid()
- self.update_donation(cancel=1)
self.delink_advance_entry_references()
self.update_payment_schedule(cancel=1)
self.set_payment_req_status()
@@ -284,8 +282,6 @@ class PaymentEntry(AccountsController):
valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity")
elif self.party_type == "Shareholder":
valid_reference_doctypes = ("Journal Entry")
- elif self.party_type == "Donor":
- valid_reference_doctypes = ("Donation")
for d in self.get("references"):
if not d.allocated_amount:
@@ -843,13 +839,6 @@ class PaymentEntry(AccountsController):
else:
update_reimbursed_amount(doc, d.allocated_amount)
- def update_donation(self, cancel=0):
- if self.payment_type == "Receive" and self.party_type == "Donor" and self.party:
- for d in self.get("references"):
- if d.reference_doctype=="Donation" and d.reference_name:
- is_paid = 0 if cancel else 1
- frappe.db.set_value("Donation", d.reference_name, "paid", is_paid)
-
def on_recurring(self, reference_doc, auto_repeat_doc):
self.reference_no = reference_doc.name
self.reference_date = nowdate()
@@ -1337,10 +1326,6 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
total_amount = ref_doc.get("grand_total")
exchange_rate = 1
outstanding_amount = ref_doc.get("outstanding_amount")
- elif reference_doctype == "Donation":
- total_amount = ref_doc.get("amount")
- outstanding_amount = total_amount
- exchange_rate = 1
elif reference_doctype == "Dunning":
total_amount = ref_doc.get("dunning_amount")
exchange_rate = 1
@@ -1611,8 +1596,6 @@ def set_party_type(dt):
party_type = "Employee"
elif dt == "Fees":
party_type = "Student"
- elif dt == "Donation":
- party_type = "Donor"
return party_type
def set_party_account(dt, dn, doc, party_type):
@@ -1640,7 +1623,7 @@ def set_party_account_currency(dt, party_account, doc):
return party_account_currency
def set_payment_type(dt, doc):
- if (dt in ("Sales Order", "Donation") or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
+ if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
payment_type = "Receive"
else:
@@ -1673,9 +1656,6 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre
elif dt == "Dunning":
grand_total = doc.grand_total
outstanding_amount = doc.grand_total
- elif dt == "Donation":
- grand_total = doc.amount
- outstanding_amount = doc.amount
elif dt == "Gratuity":
grand_total = doc.amount
outstanding_amount = flt(doc.amount) - flt(doc.paid_amount)
From 899ca8b3849995ac9164e70c4d5c73d6ebdb106a Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Mon, 31 Jan 2022 17:43:01 +0530
Subject: [PATCH 05/64] refactor: Code cleanup
---
.../workspace/non_profit/non_profit.json | 272 ------------------
.../v14_0/delete_non_profit_doctypes.py | 20 ++
.../80g_certificate_for_donation.json | 26 --
.../80g_certificate_for_donation/__init__.py | 0
.../80g_certificate_for_membership.json | 26 --
.../__init__.py | 0
6 files changed, 20 insertions(+), 324 deletions(-)
delete mode 100644 erpnext/non_profit/workspace/non_profit/non_profit.json
delete mode 100644 erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json
delete mode 100644 erpnext/regional/print_format/80g_certificate_for_donation/__init__.py
delete mode 100644 erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json
delete mode 100644 erpnext/regional/print_format/80g_certificate_for_membership/__init__.py
diff --git a/erpnext/non_profit/workspace/non_profit/non_profit.json b/erpnext/non_profit/workspace/non_profit/non_profit.json
deleted file mode 100644
index fc90475fb3..0000000000
--- a/erpnext/non_profit/workspace/non_profit/non_profit.json
+++ /dev/null
@@ -1,272 +0,0 @@
-{
- "charts": [],
- "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts \",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Member\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Non Profit Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Membership\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter Member\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters \",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Grant Application\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Membership\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Volunteer\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Chapter\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Donation\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tax Exemption Certification (India)\",\"col\":4}}]",
- "creation": "2020-03-02 17:23:47.811421",
- "docstatus": 0,
- "doctype": "Workspace",
- "for_user": "",
- "hide_custom": 0,
- "icon": "non-profit",
- "idx": 0,
- "label": "Non Profit",
- "links": [
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Management",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Type",
- "link_count": 0,
- "link_to": "Loan Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan Application",
- "link_count": 0,
- "link_to": "Loan Application",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Loan",
- "link_count": 0,
- "link_to": "Loan",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Grant Application",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Grant Application",
- "link_count": 0,
- "link_to": "Grant Application",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Member",
- "link_count": 0,
- "link_to": "Member",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership",
- "link_count": 0,
- "link_to": "Membership",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership Type",
- "link_count": 0,
- "link_to": "Membership Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Membership Settings",
- "link_count": 0,
- "link_to": "Non Profit Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer",
- "link_count": 0,
- "link_to": "Volunteer",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Volunteer Type",
- "link_count": 0,
- "link_to": "Volunteer Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Chapter",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Chapter",
- "link_count": 0,
- "link_to": "Chapter",
- "link_type": "DocType",
- "onboard": 1,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donation",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donor",
- "link_count": 0,
- "link_to": "Donor",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donor Type",
- "link_count": 0,
- "link_to": "Donor Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Donation",
- "link_count": 0,
- "link_to": "Donation",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Tax Exemption Certification (India)",
- "link_count": 0,
- "link_type": "DocType",
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Tax Exemption 80G Certificate",
- "link_count": 0,
- "link_to": "Tax Exemption 80G Certificate",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- }
- ],
- "modified": "2022-01-13 17:40:50.220877",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Non Profit",
- "owner": "Administrator",
- "parent_page": "",
- "public": 1,
- "restrict_to_domain": "Non Profit",
- "roles": [],
- "sequence_id": 18.0,
- "shortcuts": [
- {
- "label": "Member",
- "link_to": "Member",
- "type": "DocType"
- },
- {
- "label": "Non Profit Settings",
- "link_to": "Non Profit Settings",
- "type": "DocType"
- },
- {
- "label": "Membership",
- "link_to": "Membership",
- "type": "DocType"
- },
- {
- "label": "Chapter",
- "link_to": "Chapter",
- "type": "DocType"
- },
- {
- "label": "Chapter Member",
- "link_to": "Chapter Member",
- "type": "DocType"
- }
- ],
- "title": "Non Profit"
-}
\ No newline at end of file
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
index 3b3dbe4576..86355a6426 100644
--- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -6,6 +6,14 @@ def execute():
frappe.delete_doc("Workspace", "Non Profit", ignore_missing=True, force=True)
+ print_formats = frappe.get_all("Print Format", {"module": "Non Profit", "standard": "Yes"}, pluck='name')
+ for print_format in print_formats:
+ frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True)
+
+ print_formats = ['80G Certificate for Membership', '80G Certificate for Donation']
+ for print_format in print_formats:
+ frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True)
+
reports = frappe.get_all("Report", {"module": "Non Profit", "is_standard": "Yes"}, pluck='name')
for report in reports:
frappe.delete_doc("Report", report, ignore_missing=True, force=True)
@@ -17,3 +25,15 @@ def execute():
doctypes = frappe.get_all("DocType", {"module": "Non Profit", "custom": 0}, pluck='name')
for doctype in doctypes:
frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+ doctypes = ['Tax Exemption 80G Certificate', 'Tax Exemption 80G Certificate Detail']
+ for doctype in doctypes:
+ frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+ custom_fields = [
+ {"dt": "Member", "fieldname": "pan_number"},
+ {"dt": "Donor", "fieldname": "pan_number"},
+ ]
+ for field in custom_fields:
+ custom_field = frappe.db.get_value("Custom Field", field)
+ frappe.delete_doc("Custom Field", custom_field, ignore_missing=True)
diff --git a/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json b/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json
deleted file mode 100644
index a8da0bd209..0000000000
--- a/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "absolute_value": 0,
- "align_labels_right": 0,
- "creation": "2021-02-22 00:17:33.878581",
- "css": ".details {\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n line-height: 150%;\n}\n\n.certificate-footer {\n font-size: 15px;\n font-family: Tahoma, sans-serif;\n line-height: 140%;\n margin-top: 120px;\n}\n\n.company-address {\n color: #666666;\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n}",
- "custom_format": 1,
- "default_print_language": "en",
- "disabled": 0,
- "doc_type": "Tax Exemption 80G Certificate",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "{% if letter_head and not no_letterhead -%}\n {{ letter_head }}
\n{%- endif %}\n\n\n
{{ doc.company }} 80G Donor Certificate \n
\n \n\n\n
{{ _(\"Certificate No. : \") }} {{ doc.name }}
\n
\n \t{{ _(\"Date\") }} : {{ doc.get_formatted(\"date\") }} \n
\n
\n \n
\n\n This is to confirm that the {{ doc.company }} received an amount of
{{doc.get_formatted(\"amount\")}} \n from
{{ doc.donor_name }} \n {% if doc.pan_number -%}\n bearing PAN Number {{ doc.member_pan_number }}\n {%- endif %}\n\n via the Mode of Payment {{doc.mode_of_payment}}\n\n {% if doc.razorpay_payment_id -%}\n bearing RazorPay Payment ID {{ doc.razorpay_payment_id }}\n {%- endif %}\n\n on {{ doc.get_formatted(\"date_of_donation\") }}\n
\n \n
\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n
\n\n
\n
\n\n \n {{doc.company_address_display }}
\n\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2021-02-22 00:20:08.516600",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "80G Certificate for Donation",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Jinja",
- "raw_printing": 0,
- "show_section_headings": 0,
- "standard": "Yes"
-}
\ No newline at end of file
diff --git a/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py b/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json b/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json
deleted file mode 100644
index f1b15aab29..0000000000
--- a/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "absolute_value": 0,
- "align_labels_right": 0,
- "creation": "2021-02-15 16:53:55.026611",
- "css": ".details {\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n line-height: 150%;\n}\n\n.certificate-footer {\n font-size: 15px;\n font-family: Tahoma, sans-serif;\n line-height: 140%;\n margin-top: 120px;\n}\n\n.company-address {\n color: #666666;\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n}",
- "custom_format": 1,
- "default_print_language": "en",
- "disabled": 0,
- "doc_type": "Tax Exemption 80G Certificate",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "{% if letter_head and not no_letterhead -%}\n {{ letter_head }}
\n{%- endif %}\n\n\n
{{ doc.company }} Members 80G Donor Certificate \n Financial Cycle {{ doc.fiscal_year }} \n\n \n\n\n
{{ _(\"Certificate No. : \") }} {{ doc.name }}
\n
\n \t{{ _(\"Date\") }} : {{ doc.get_formatted(\"date\") }} \n
\n
\n \n
\n This is to confirm that the {{ doc.company }} received a total amount of
{{doc.get_formatted(\"total\")}} \n from
{{ doc.member_name }} \n {% if doc.pan_number -%}\n bearing PAN Number {{ doc.member_pan_number }}\n {%- endif %}\n as per the payment details given below:\n \n
\n
\n \t\n \t\t\n \t\t\t{{ _(\"Date\") }} \n \t\t\t{{ _(\"Amount\") }} \n \t\t\t{{ _(\"Invoice ID\") }} \n \t\t \n \t \n \t\n \t\t{%- for payment in doc.payments -%}\n \t\t\n \t\t\t {{ payment.date }} \n \t\t\t{{ payment.get_formatted(\"amount\") }} \n \t\t\t{{ payment.invoice_id }} \n \t\t \n \t\t{%- endfor -%}\n \t \n
\n \n
\n \n
\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n
\n\n
\n
\n\n \n {{doc.company_address_display }}
\n\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2021-02-21 23:29:00.778973",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "80G Certificate for Membership",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Jinja",
- "raw_printing": 0,
- "show_section_headings": 0,
- "standard": "Yes"
-}
\ No newline at end of file
diff --git a/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py b/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
From dddeef71799bdc9c0c787fc1fee9dd05e3c998e0 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 3 Feb 2022 16:41:36 +0530
Subject: [PATCH 06/64] chore: Clean up whitespace
---
erpnext/patches.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 09cfdcee82..a8134f20fc 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -336,7 +336,6 @@ erpnext.patches.v13_0.enable_provisional_accounting
erpnext.patches.v13_0.non_profit_deprecation_warning
erpnext.patches.v14_0.delete_non_profit_doctypes
-
[post_model_sync]
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
From d636c3fb04ae5b1b95c67052bfb5f894e4cbf4f4 Mon Sep 17 00:00:00 2001
From: Devin Slauenwhite
Date: Wed, 9 Feb 2022 10:52:38 -0500
Subject: [PATCH 07/64] test: many users linked to customer shopping cart
---
.../shopping_cart/test_shopping_cart.py | 25 +++++++++++--------
erpnext/tests/utils.py | 14 +++++++++++
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
index 8519e68d09..05c874af98 100644
--- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
+++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
@@ -57,13 +57,19 @@ class TestShoppingCart(unittest.TestCase):
return quotation
def test_get_cart_customer(self):
- self.login_as_customer()
+ def validate_quotation():
+ # test if quotation with customer is fetched
+ quotation = _get_cart_quotation()
+ self.assertEqual(quotation.quotation_to, "Customer")
+ self.assertEqual(quotation.party_name, "_Test Customer")
+ self.assertEqual(quotation.contact_email, frappe.session.user)
+ return quotation
- # test if quotation with customer is fetched
- quotation = _get_cart_quotation()
- self.assertEqual(quotation.quotation_to, "Customer")
- self.assertEqual(quotation.party_name, "_Test Customer")
- self.assertEqual(quotation.contact_email, frappe.session.user)
+ self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer")
+ validate_quotation()
+
+ self.login_as_customer()
+ quotation = validate_quotation()
return quotation
@@ -254,10 +260,9 @@ class TestShoppingCart(unittest.TestCase):
self.create_user_if_not_exists("test_cart_user@example.com")
frappe.set_user("test_cart_user@example.com")
- def login_as_customer(self):
- self.create_user_if_not_exists("test_contact_customer@example.com",
- "_Test Contact For _Test Customer")
- frappe.set_user("test_contact_customer@example.com")
+ def login_as_customer(self, email="test_contact_customer@example.com", name="_Test Contact For _Test Customer"):
+ self.create_user_if_not_exists(email, name)
+ frappe.set_user(email)
def clear_existing_quotations(self):
quotations = frappe.get_all("Quotation", filters={
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index 2bd7e9e71d..40c95eb7a3 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -66,6 +66,20 @@ def create_test_contact_and_address():
contact.add_phone("+91 0000000000", is_primary_phone=True)
contact.insert()
+ contact_two = frappe.get_doc({
+ "doctype": 'Contact',
+ "first_name": "_Test Contact 2 for _Test Customer",
+ "links": [
+ {
+ "link_doctype": "Customer",
+ "link_name": "_Test Customer"
+ }
+ ]
+ })
+ contact_two.add_email("test_contact_two_customer@example.com", is_primary=True)
+ contact_two.add_phone("+92 0000000000", is_primary_phone=True)
+ contact_two.insert()
+
@contextmanager
def change_settings(doctype, settings_dict):
From 34ad5b1abf534f55876fcfac2852df2ea42ecb41 Mon Sep 17 00:00:00 2001
From: Devin Slauenwhite
Date: Wed, 9 Feb 2022 10:53:24 -0500
Subject: [PATCH 08/64] fix: get cart for logged in user.
---
erpnext/e_commerce/shopping_cart/cart.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py
index 458cf69af7..372aed0b95 100644
--- a/erpnext/e_commerce/shopping_cart/cart.py
+++ b/erpnext/e_commerce/shopping_cart/cart.py
@@ -310,7 +310,7 @@ def _get_cart_quotation(party=None):
party = get_party()
quotation = frappe.get_all("Quotation", fields=["name"], filters=
- {"party_name": party.name, "order_type": "Shopping Cart", "docstatus": 0},
+ {"party_name": party.name, "contact_email": frappe.session.user, "order_type": "Shopping Cart", "docstatus": 0},
order_by="modified desc", limit_page_length=1)
if quotation:
From 49bee568a1d5bcfc315f539af734bc55a84a35ef Mon Sep 17 00:00:00 2001
From: Devin Slauenwhite
Date: Wed, 9 Feb 2022 12:03:05 -0500
Subject: [PATCH 09/64] fix: get cart items for logged in user.
---
erpnext/e_commerce/product_data_engine/query.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py
index 007bf8b348..cfc3c7b357 100644
--- a/erpnext/e_commerce/product_data_engine/query.py
+++ b/erpnext/e_commerce/product_data_engine/query.py
@@ -264,7 +264,7 @@ class ProductQuery:
customer = get_customer(silent=True)
if customer:
quotation = frappe.get_all("Quotation", fields=["name"], filters=
- {"party_name": customer, "order_type": "Shopping Cart", "docstatus": 0},
+ {"party_name": customer, "contact_email": frappe.session.user, "order_type": "Shopping Cart", "docstatus": 0},
order_by="modified desc", limit_page_length=1)
if quotation:
items = frappe.get_all(
@@ -298,4 +298,4 @@ class ProductQuery:
# slice results manually
result[:self.page_length]
- return result
\ No newline at end of file
+ return result
From 72fe5590313f82ee22421339ca780ba9d4249ed1 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 17 Feb 2022 08:33:15 +0530
Subject: [PATCH 10/64] refactor: Remove non profit templates
---
.../templates/pages/non_profit/__init__.py | 0
.../pages/non_profit/join-chapter.html | 59 -------------------
.../pages/non_profit/join_chapter.js | 12 ----
.../pages/non_profit/join_chapter.py | 23 --------
.../pages/non_profit/leave-chapter.html | 42 -------------
.../pages/non_profit/leave_chapter.py | 8 ---
6 files changed, 144 deletions(-)
delete mode 100644 erpnext/templates/pages/non_profit/__init__.py
delete mode 100644 erpnext/templates/pages/non_profit/join-chapter.html
delete mode 100644 erpnext/templates/pages/non_profit/join_chapter.js
delete mode 100644 erpnext/templates/pages/non_profit/join_chapter.py
delete mode 100644 erpnext/templates/pages/non_profit/leave-chapter.html
delete mode 100644 erpnext/templates/pages/non_profit/leave_chapter.py
diff --git a/erpnext/templates/pages/non_profit/__init__.py b/erpnext/templates/pages/non_profit/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/templates/pages/non_profit/join-chapter.html b/erpnext/templates/pages/non_profit/join-chapter.html
deleted file mode 100644
index 4923efc4e8..0000000000
--- a/erpnext/templates/pages/non_profit/join-chapter.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
-
-{% macro chapter_button() %}
-
- Go to Chapter Page
-{% endmacro %}
-{% if frappe.session.user=='Guest' %}
- Please signup and login to join this chapter
- Login
-{% else %}
- {% if already_member %}
- You are already a member of {{ chapter.name }}!
- {{ chapter_button() }}
- Leave Chapter
- {% else %}
- {% if request.method=='POST' %}
- Welcome to chapter {{ chapter.name }}!
- {{ chapter_button() }}
- {% else %}
-
- {% endif %}
- {% endif %}
-
-{% endif %}
-
-{% endblock %}
diff --git a/erpnext/templates/pages/non_profit/join_chapter.js b/erpnext/templates/pages/non_profit/join_chapter.js
deleted file mode 100644
index e2bc8bca71..0000000000
--- a/erpnext/templates/pages/non_profit/join_chapter.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2017, EOSSF and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Chapter Member', {
- onsubmit: function (frm) {
- console.log("here" + frappe.session.user)
- // body...
- }
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/templates/pages/non_profit/join_chapter.py b/erpnext/templates/pages/non_profit/join_chapter.py
deleted file mode 100644
index 7caf87db2b..0000000000
--- a/erpnext/templates/pages/non_profit/join_chapter.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import frappe
-
-
-def get_context(context):
- context.no_cache = True
- chapter = frappe.get_doc('Chapter', frappe.form_dict.name)
- if frappe.session.user!='Guest':
- if frappe.session.user in [d.user for d in chapter.members if d.enabled == 1]:
- context.already_member = True
- else:
- if frappe.request.method=='GET':
- pass
- elif frappe.request.method=='POST':
- chapter.append('members', dict(
- user=frappe.session.user,
- introduction=frappe.form_dict.introduction,
- website_url=frappe.form_dict.website_url,
- enabled=1
- ))
- chapter.save(ignore_permissions=1)
- frappe.db.commit()
-
- context.chapter = chapter
diff --git a/erpnext/templates/pages/non_profit/leave-chapter.html b/erpnext/templates/pages/non_profit/leave-chapter.html
deleted file mode 100644
index fd7658b3b1..0000000000
--- a/erpnext/templates/pages/non_profit/leave-chapter.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{% extends "templates/web.html" %}
-{% block page_content %}
-
- {% if member_deleted %}
- You are not a member of {{ chapter.name }}!
-
-
-
- Why do you want to leave this chapter
-
-
- Submit
-
-
-
- Please signup and login to join this chapter
-
- Become Member agian
- {% endif %}
-
-{% endblock %}
diff --git a/erpnext/templates/pages/non_profit/leave_chapter.py b/erpnext/templates/pages/non_profit/leave_chapter.py
deleted file mode 100644
index 65908e1dd9..0000000000
--- a/erpnext/templates/pages/non_profit/leave_chapter.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import frappe
-
-
-def get_context(context):
- context.no_cache = True
- chapter = frappe.get_doc('Chapter', frappe.form_dict.name)
- context.member_deleted = True
- context.chapter = chapter
From b5ff9b27bdf762c4118974d69ef8b78b2c228348 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 17 Feb 2022 08:33:55 +0530
Subject: [PATCH 11/64] refactor: Clean up non-profit setup
---
erpnext/__init__.py | 8 ------
erpnext/patches.txt | 2 +-
.../v14_0/delete_non_profit_doctypes.py | 28 ++++++++++++++-----
erpnext/regional/india/setup.py | 9 ------
4 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 0b4696c803..a44c8fabe3 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -130,11 +130,3 @@ def allow_regional(fn):
return fn(*args, **kwargs)
return caller
-
-def get_last_membership(member):
- '''Returns last membership if exists'''
- last_membership = frappe.get_all('Membership', 'name,to_date,membership_type',
- dict(member=member, paid=1), order_by='to_date desc', limit=1)
-
- if last_membership:
- return last_membership[0]
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index a8134f20fc..7bc70714a2 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -334,7 +334,6 @@ erpnext.patches.v13_0.update_asset_quantity_field
erpnext.patches.v13_0.delete_bank_reconciliation_detail
erpnext.patches.v13_0.enable_provisional_accounting
erpnext.patches.v13_0.non_profit_deprecation_warning
-erpnext.patches.v14_0.delete_non_profit_doctypes
[post_model_sync]
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
@@ -351,3 +350,4 @@ erpnext.patches.v12_0.add_company_link_to_einvoice_settings
erpnext.patches.v14_0.migrate_cost_center_allocations
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
erpnext.patches.v13_0.shopping_cart_to_ecommerce
+erpnext.patches.v14_0.delete_non_profit_doctypes
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
index 86355a6426..39f2fecf08 100644
--- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -30,10 +30,24 @@ def execute():
for doctype in doctypes:
frappe.delete_doc("DocType", doctype, ignore_missing=True)
- custom_fields = [
- {"dt": "Member", "fieldname": "pan_number"},
- {"dt": "Donor", "fieldname": "pan_number"},
- ]
- for field in custom_fields:
- custom_field = frappe.db.get_value("Custom Field", field)
- frappe.delete_doc("Custom Field", custom_field, ignore_missing=True)
+ forms = ['grant-application', 'certification-application', 'certification-application-usd']
+ for form in forms:
+ frappe.delete_doc("Web Form", form, ignore_missing=True)
+
+ custom_fields = {
+ 'Member': ['pan_number'],
+ 'Donor': ['pan_number'],
+ 'Company': [
+ 'non_profit_section', 'company_80g_number', 'with_effect_from',
+ 'non_profit_column_break', 'pan_details'
+ ],
+ }
+
+ for doc, fields in custom_fields.items():
+ filters = {
+ 'dt': doc,
+ 'fieldname': ['in', fields]
+ }
+ records = frappe.get_all('Custom Field', filters=filters, pluck='name')
+ for record in records:
+ frappe.delete_doc('Custom Field', record, ignore_missing=True, force=True)
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index c2e83045c7..8f3ef62c12 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -610,15 +610,6 @@ def get_custom_fields():
dict(fieldname='hra_column_break', fieldtype='Column Break', insert_after='hra_component'),
dict(fieldname='arrear_component', label='Arrear Component',
fieldtype='Link', options='Salary Component', insert_after='hra_column_break'),
- dict(fieldname='non_profit_section', label='Non Profit Settings',
- fieldtype='Section Break', insert_after='arrear_component', collapsible=1),
- dict(fieldname='company_80g_number', label='80G Number',
- fieldtype='Data', insert_after='non_profit_section'),
- dict(fieldname='with_effect_from', label='80G With Effect From',
- fieldtype='Date', insert_after='company_80g_number'),
- dict(fieldname='non_profit_column_break', fieldtype='Column Break', insert_after='with_effect_from'),
- dict(fieldname='pan_details', label='PAN Number',
- fieldtype='Data', insert_after='non_profit_column_break')
],
'Employee Tax Exemption Declaration':[
dict(fieldname='hra_section', label='HRA Exemption',
From fb59247182a4511fbdec106cc0ca0f68253b8579 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 17 Feb 2022 15:15:10 +0530
Subject: [PATCH 12/64] fix: Delete party type records in patch
---
erpnext/patches/v14_0/delete_non_profit_doctypes.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
index 39f2fecf08..5b1cfefa4b 100644
--- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -34,6 +34,13 @@ def execute():
for form in forms:
frappe.delete_doc("Web Form", form, ignore_missing=True)
+ custom_records = [
+ {"doctype": "Party Type", "name": "Member"},
+ {"doctype": "Party Type", "name": "Donor"},
+ ]
+ for record in custom_records:
+ frappe.delete_doc(record['doctype'], record['name'], ignore_missing=True)
+
custom_fields = {
'Member': ['pan_number'],
'Donor': ['pan_number'],
From 358734dceabbd503cbd2ae3d8401fda960140a80 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Thu, 17 Feb 2022 16:31:27 +0530
Subject: [PATCH 13/64] fix: Skip deletion if linked docs exists
---
erpnext/patches/v14_0/delete_non_profit_doctypes.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
index 5b1cfefa4b..d53aecca92 100644
--- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -39,7 +39,10 @@ def execute():
{"doctype": "Party Type", "name": "Donor"},
]
for record in custom_records:
- frappe.delete_doc(record['doctype'], record['name'], ignore_missing=True)
+ try:
+ frappe.delete_doc(record['doctype'], record['name'], ignore_missing=True)
+ except frappe.LinkExistsError:
+ pass
custom_fields = {
'Member': ['pan_number'],
From 555b1335f65cca4f77c28294e153002a39e114a4 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 17 Feb 2022 19:15:30 +0530
Subject: [PATCH 14/64] feat: Bank Reconciliation for loan documents
---
.../bank_reconciliation_tool.py | 73 ++++++++++++++++++-
.../loan_disbursement/loan_disbursement.json | 47 ++++++++++--
.../loan_disbursement/loan_disbursement.py | 12 +--
.../loan_repayment/loan_repayment.json | 52 ++++++++++++-
.../doctype/loan_repayment/loan_repayment.py | 24 +++---
.../dialog_manager.js | 17 ++++-
6 files changed, 190 insertions(+), 35 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 4211bd0169..26078d6329 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -275,6 +275,10 @@ def check_matching(bank_account, company, transaction, document_types):
}
matching_vouchers = []
+
+ matching_vouchers.extend(get_loan_vouchers(bank_account, transaction,
+ document_types, filters))
+
for query in subquery:
matching_vouchers.extend(
frappe.db.sql(query, filters,)
@@ -311,6 +315,74 @@ def get_queries(bank_account, company, transaction, document_types):
return queries
+def get_loan_vouchers(bank_account, transaction, document_types, filters):
+ vouchers = []
+ amount_condition = True if "exact_match" in document_types else False
+
+ if transaction.withdrawal > 0 and "loan_disbursement" in document_types:
+ vouchers.append(get_ld_matching_query(bank_account, amount_condition, filters))
+
+ if transaction.deposit > 0 and "loan_repayment" in document_types:
+ vouchers.append(get_lr_matching_query(bank_account, amount_condition, filters))
+
+def get_ld_matching_query(bank_account, amount_condition, filters):
+ loan_disbursement = frappe.qb.DocType("Loan Disbursement")
+ query = frappe.qb.from_(loan_disbursement).select(
+ loan_disbursement.name,
+ loan_disbursement.disbursed_amount,
+ loan_disbursement.reference_number,
+ loan_disbursement.reference_date,
+ loan_disbursement.applicant_type,
+ loan_disbursement.disbursement_date
+ ).where(
+ loan_disbursement.docstatus == 1
+ ).where(
+ loan_disbursement.clearance_date.isnull()
+ ).where(
+ loan_disbursement.disbursement_account == bank_account
+ )
+
+ if amount_condition:
+ query.where(
+ loan_disbursement.disbursed_amount == filters.get('amount')
+ )
+ else:
+ query.where(
+ loan_disbursement.disbursed_amount <= filters.get('amount')
+ )
+
+ vouchers = query.run(as_dict=1)
+ return vouchers
+
+def get_lr_matching_query(bank_account, amount_condition, filters):
+ loan_repayment = frappe.qb.DocType("Loan Repayment")
+ query = frappe.qb.from_(loan_repayment).select(
+ loan_repayment.name,
+ loan_repayment.paid_amount,
+ loan_repayment.reference_number,
+ loan_repayment.reference_date,
+ loan_repayment.applicant_type,
+ loan_repayment.posting_date
+ ).where(
+ loan_repayment.docstatus == 1
+ ).where(
+ loan_repayment.clearance_date.isnull()
+ ).where(
+ loan_repayment.disbursement_account == bank_account
+ )
+
+ if amount_condition:
+ query.where(
+ loan_repayment.paid_amount == filters.get('amount')
+ )
+ else:
+ query.where(
+ loan_repayment.paid_amount <= filters.get('amount')
+ )
+
+ vouchers = query.run(as_dict=1)
+ return vouchers
+
def get_pe_matching_query(amount_condition, account_from_to, transaction):
# get matching payment entries query
if transaction.deposit > 0:
@@ -348,7 +420,6 @@ def get_je_matching_query(amount_condition, transaction):
# We have mapping at the bank level
# So one bank could have both types of bank accounts like asset and liability
# So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type
- company_account = frappe.get_value("Bank Account", transaction.bank_account, "account")
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
return f"""
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index 7811d56a75..50926d7726 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
@@ -14,11 +14,15 @@
"applicant",
"section_break_7",
"disbursement_date",
+ "clearance_date",
"column_break_8",
"disbursed_amount",
"accounting_dimensions_section",
"cost_center",
- "customer_details_section",
+ "accounting_details",
+ "disbursement_account",
+ "column_break_16",
+ "loan_account",
"bank_account",
"disbursement_references_section",
"reference_date",
@@ -106,11 +110,6 @@
"fieldtype": "Section Break",
"label": "Disbursement Details"
},
- {
- "fieldname": "customer_details_section",
- "fieldtype": "Section Break",
- "label": "Customer Details"
- },
{
"fetch_from": "against_loan.applicant_type",
"fieldname": "applicant_type",
@@ -149,15 +148,48 @@
"fieldname": "reference_number",
"fieldtype": "Data",
"label": "Reference Number"
+ },
+ {
+ "fieldname": "clearance_date",
+ "fieldtype": "Date",
+ "label": "Clearance Date",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "accounting_details",
+ "fieldtype": "Section Break",
+ "label": "Accounting Details"
+ },
+ {
+ "fetch_from": "against_loan.disbursement_account",
+ "fieldname": "disbursement_account",
+ "fieldtype": "Link",
+ "label": "Disbursement Account",
+ "options": "Account",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "against_loan.loan_account",
+ "fieldname": "loan_account",
+ "fieldtype": "Link",
+ "label": "Loan Account",
+ "options": "Account",
+ "read_only": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-19 18:09:32.175355",
+ "modified": "2022-02-17 18:23:44.157598",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Disbursement",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -194,5 +226,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index df3aadfb18..54a03b92b5 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -42,9 +42,6 @@ class LoanDisbursement(AccountsController):
if not self.posting_date:
self.posting_date = self.disbursement_date or nowdate()
- if not self.bank_account and self.applicant_type == "Customer":
- self.bank_account = frappe.db.get_value("Customer", self.applicant, "default_bank_account")
-
def validate_disbursal_amount(self):
possible_disbursal_amount = get_disbursal_amount(self.against_loan)
@@ -117,12 +114,11 @@ class LoanDisbursement(AccountsController):
def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = []
- loan_details = frappe.get_doc("Loan", self.against_loan)
gle_map.append(
self.get_gl_dict({
- "account": loan_details.loan_account,
- "against": loan_details.disbursement_account,
+ "account": self.loan_account,
+ "against": self.disbursement_account,
"debit": self.disbursed_amount,
"debit_in_account_currency": self.disbursed_amount,
"against_voucher_type": "Loan",
@@ -137,8 +133,8 @@ class LoanDisbursement(AccountsController):
gle_map.append(
self.get_gl_dict({
- "account": loan_details.disbursement_account,
- "against": loan_details.loan_account,
+ "account": self.disbursement_account,
+ "against": self.loan_account,
"credit": self.disbursed_amount,
"credit_in_account_currency": self.disbursed_amount,
"against_voucher_type": "Loan",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 93ef217042..766602de86 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -1,7 +1,7 @@
{
"actions": [],
"autoname": "LM-REP-.####",
- "creation": "2019-09-03 14:44:39.977266",
+ "creation": "2022-01-25 10:30:02.767941",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
@@ -13,6 +13,7 @@
"column_break_3",
"company",
"posting_date",
+ "clearance_date",
"rate_of_interest",
"payroll_payable_account",
"is_term_loan",
@@ -37,7 +38,12 @@
"total_penalty_paid",
"total_interest_paid",
"repayment_details",
- "amended_from"
+ "amended_from",
+ "accounting_details_section",
+ "repayment_account",
+ "penalty_income_account",
+ "column_break_36",
+ "loan_account"
],
"fields": [
{
@@ -260,12 +266,52 @@
"fieldname": "repay_from_salary",
"fieldtype": "Check",
"label": "Repay From Salary"
+ },
+ {
+ "fieldname": "clearance_date",
+ "fieldtype": "Date",
+ "label": "Clearance Date",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "accounting_details_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Details"
+ },
+ {
+ "fetch_from": "against_loan.payment_account",
+ "fieldname": "repayment_account",
+ "fieldtype": "Link",
+ "label": "Repayment Account",
+ "options": "Account",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_36",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "against_loan.loan_account",
+ "fieldname": "loan_account",
+ "fieldtype": "Link",
+ "label": "Loan Account",
+ "options": "Account",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "against_loan.penalty_income_account",
+ "fieldname": "penalty_income_account",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Penalty Income Account",
+ "options": "Account"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2022-01-06 01:51:06.707782",
+ "modified": "2022-02-17 19:10:07.742298",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Repayment",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index f3ed611255..67c2b1ee14 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -310,7 +310,6 @@ class LoanRepayment(AccountsController):
def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = []
- loan_details = frappe.get_doc("Loan", self.against_loan)
if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(self.shortfall_amount,
@@ -323,13 +322,13 @@ class LoanRepayment(AccountsController):
if self.repay_from_salary:
payment_account = self.payroll_payable_account
else:
- payment_account = loan_details.payment_account
+ payment_account = self.payment_account
if self.total_penalty_paid:
gle_map.append(
self.get_gl_dict({
- "account": loan_details.loan_account,
- "against": loan_details.payment_account,
+ "account": self.loan_account,
+ "against": payment_account,
"debit": self.total_penalty_paid,
"debit_in_account_currency": self.total_penalty_paid,
"against_voucher_type": "Loan",
@@ -344,8 +343,8 @@ class LoanRepayment(AccountsController):
gle_map.append(
self.get_gl_dict({
- "account": loan_details.penalty_income_account,
- "against": loan_details.loan_account,
+ "account": self.penalty_income_account,
+ "against": self.loan_account,
"credit": self.total_penalty_paid,
"credit_in_account_currency": self.total_penalty_paid,
"against_voucher_type": "Loan",
@@ -359,8 +358,7 @@ class LoanRepayment(AccountsController):
gle_map.append(
self.get_gl_dict({
"account": payment_account,
- "against": loan_details.loan_account + ", " + loan_details.interest_income_account
- + ", " + loan_details.penalty_income_account,
+ "against": self.loan_account + ", " + self.penalty_income_account,
"debit": self.amount_paid,
"debit_in_account_currency": self.amount_paid,
"against_voucher_type": "Loan",
@@ -368,16 +366,16 @@ class LoanRepayment(AccountsController):
"remarks": remarks,
"cost_center": self.cost_center,
"posting_date": getdate(self.posting_date),
- "party_type": loan_details.applicant_type if self.repay_from_salary else '',
- "party": loan_details.applicant if self.repay_from_salary else ''
+ "party_type": self.applicant_type if self.repay_from_salary else '',
+ "party": self.applicant if self.repay_from_salary else ''
})
)
gle_map.append(
self.get_gl_dict({
- "account": loan_details.loan_account,
- "party_type": loan_details.applicant_type,
- "party": loan_details.applicant,
+ "account": self.loan_account,
+ "party_type": self.applicant_type,
+ "party": self.applicant,
"against": payment_account,
"credit": self.amount_paid,
"credit_in_account_currency": self.amount_paid,
diff --git a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
index ca73393c54..214a1be134 100644
--- a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
+++ b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
@@ -181,6 +181,12 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
fieldname: "journal_entry",
onchange: () => this.update_options(),
},
+ {
+ fieldtype: "Check",
+ label: "Loan Repayment",
+ fieldname: "loan_repayment",
+ onchange: () => this.update_options(),
+ },
{
fieldname: "column_break_5",
fieldtype: "Column Break",
@@ -191,13 +197,18 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
fieldname: "sales_invoice",
onchange: () => this.update_options(),
},
-
{
fieldtype: "Check",
label: "Purchase Invoice",
fieldname: "purchase_invoice",
onchange: () => this.update_options(),
},
+ {
+ fieldtype: "Check",
+ label: "Show Only Exact Amount",
+ fieldname: "exact_match",
+ onchange: () => this.update_options(),
+ },
{
fieldname: "column_break_5",
fieldtype: "Column Break",
@@ -210,8 +221,8 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
},
{
fieldtype: "Check",
- label: "Show Only Exact Amount",
- fieldname: "exact_match",
+ label: "Loan Disbursement",
+ fieldname: "loan_disbursement",
onchange: () => this.update_options(),
},
{
From 5a2b571aa9e0f448d2030e1901dfb9ec3e547d46 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 18 Feb 2022 20:05:49 +0530
Subject: [PATCH 15/64] fix: Validate party account with company
---
.../accounts/doctype/payment_entry/payment_entry.py | 2 +-
.../sales_taxes_and_charges_template.py | 2 +-
erpnext/accounts/party.py | 5 ++++-
erpnext/controllers/accounts_controller.py | 12 +++++-------
4 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 02a144d3e7..0d8f079d7a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1077,7 +1077,7 @@ def get_outstanding_reference_documents(args):
if d.voucher_type in ("Purchase Invoice"):
d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
- # Get all SO / PO which are not fully billed or aginst which full advance not paid
+ # Get all SO / PO which are not fully billed or against which full advance not paid
orders_to_be_billed = []
if (args.get("party_type") != "Student"):
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"),
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
index b5909447dc..1d30934df9 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
@@ -46,7 +46,7 @@ def valdiate_taxes_and_charges_template(doc):
for tax in doc.get("taxes"):
validate_taxes_and_charges(tax)
- validate_account_head(tax, doc)
+ validate_account_head(tax.idx, tax.account_head, doc.company)
validate_cost_center(tax, doc)
validate_inclusive_tax(tax, doc)
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index c13bc23c15..d6f6c5bcb6 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -307,7 +307,7 @@ def validate_party_gle_currency(party_type, party, company, party_account_curren
.format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency)
def validate_party_accounts(doc):
-
+ from erpnext.controllers.accounts_controller import validate_account_head
companies = []
for account in doc.get("accounts"):
@@ -330,6 +330,9 @@ def validate_party_accounts(doc):
if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency:
frappe.throw(_("Billing currency must be equal to either default company's currency or party account currency"))
+ # validate if account is mapped for same company
+ validate_account_head(account.idx, account.account, account.company)
+
@frappe.whitelist()
def get_due_date(posting_date, party_type, party, company=None, bill_date=None):
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index d05787fdfb..7913a39329 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1566,13 +1566,12 @@ def validate_taxes_and_charges(tax):
tax.rate = None
-def validate_account_head(tax, doc):
- company = frappe.get_cached_value('Account',
- tax.account_head, 'company')
+def validate_account_head(idx, account, company):
+ account_company = frappe.get_cached_value('Account', account, 'company')
- if company != doc.company:
+ if account_company != company:
frappe.throw(_('Row {0}: Account {1} does not belong to Company {2}')
- .format(tax.idx, frappe.bold(tax.account_head), frappe.bold(doc.company)), title=_('Invalid Account'))
+ .format(idx, frappe.bold(account), frappe.bold(company)), title=_('Invalid Account'))
def validate_cost_center(tax, doc):
@@ -1955,8 +1954,7 @@ def update_bin_on_delete(row, doctype):
qty_dict["ordered_qty"] = get_ordered_qty(row.item_code, row.warehouse)
- if row.warehouse:
- update_bin_qty(row.item_code, row.warehouse, qty_dict)
+ update_bin_qty(row.item_code, row.warehouse, qty_dict)
def validate_and_delete_children(parent, data):
deleted_children = []
From a0bdcbd0cd551895af63955343f517051917c8eb Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 21 Feb 2022 11:44:00 +0530
Subject: [PATCH 16/64] fix: Add patch for account fields
---
erpnext/patches.txt | 1 +
.../v13_0/update_accounts_in_loan_docs.py | 37 +++++++++++++++++++
2 files changed, 38 insertions(+)
create mode 100644 erpnext/patches/v13_0/update_accounts_in_loan_docs.py
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d104bc003c..b24bf0a7e0 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -352,3 +352,4 @@ erpnext.patches.v13_0.shopping_cart_to_ecommerce
erpnext.patches.v13_0.update_disbursement_account
erpnext.patches.v13_0.update_reserved_qty_closed_wo
erpnext.patches.v14_0.delete_amazon_mws_doctype
+erpnext.patches.v13_0.update_accounts_in_loan_docs
diff --git a/erpnext/patches/v13_0/update_accounts_in_loan_docs.py b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py
new file mode 100644
index 0000000000..440f912be2
--- /dev/null
+++ b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py
@@ -0,0 +1,37 @@
+import frappe
+
+
+def execute():
+ ld = frappe.qb.DocType("Loan Disbursement").as_("ld")
+ lr = frappe.qb.DocType("Loan Repayment").as_("lr")
+ loan = frappe.qb.DocType("Loan")
+
+ frappe.qb.update(
+ ld
+ ).inner_join(
+ loan
+ ).on(
+ loan.name == ld.against_loan
+ ).set(
+ ld.disbursement_account, loan.disbursement_account
+ ).set(
+ ld.loan_account, loan.loan_account
+ ).where(
+ ld.docstatus < 2
+ ).run()
+
+ frappe.qb.update(
+ lr
+ ).inner_join(
+ loan
+ ).on(
+ loan.name == lr.against_loan
+ ).set(
+ lr.payment_account, loan.payment_account
+ ).set(
+ lr.loan_account, loan.loan_account
+ ).set(
+ lr.penalty_income_account, loan.penalty_income_account
+ ).where(
+ lr.docstatus < 2
+ ).run()
From 295cbb0ff22b04c705148d727d96f70b836fee93 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 21 Feb 2022 11:45:23 +0530
Subject: [PATCH 17/64] fix: Update queries in Bank Reconciliation Tool
---
.../bank_reconciliation_tool.py | 57 ++++++++++++++++---
.../bank_transaction/bank_transaction.py | 13 ++++-
.../loan_repayment/loan_repayment.json | 6 +-
3 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 26078d6329..f3351ddcba 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -7,6 +7,7 @@ import json
import frappe
from frappe import _
from frappe.model.document import Document
+from frappe.query_builder.custom import ConstantColumn
from frappe.utils import flt
from erpnext import get_company_currency
@@ -320,14 +321,34 @@ def get_loan_vouchers(bank_account, transaction, document_types, filters):
amount_condition = True if "exact_match" in document_types else False
if transaction.withdrawal > 0 and "loan_disbursement" in document_types:
- vouchers.append(get_ld_matching_query(bank_account, amount_condition, filters))
+ vouchers.extend(get_ld_matching_query(bank_account, amount_condition, filters))
if transaction.deposit > 0 and "loan_repayment" in document_types:
- vouchers.append(get_lr_matching_query(bank_account, amount_condition, filters))
+ vouchers.extend(get_lr_matching_query(bank_account, amount_condition, filters))
+
+ return vouchers
def get_ld_matching_query(bank_account, amount_condition, filters):
loan_disbursement = frappe.qb.DocType("Loan Disbursement")
+ matching_reference = loan_disbursement.reference_number == filters.get("reference_number")
+ matching_party = loan_disbursement.applicant_type == filters.get("party_type") and \
+ loan_disbursement.applicant == filters.get("party")
+
+ rank = (
+ frappe.qb.terms.Case()
+ .when(matching_reference, 1)
+ .else_(0)
+ )
+
+ rank1 = (
+ frappe.qb.terms.Case()
+ .when(matching_party, 1)
+ .else_(0)
+ )
+
query = frappe.qb.from_(loan_disbursement).select(
+ rank + rank1 + 1,
+ ConstantColumn("Loan Disbursement").as_("doctype"),
loan_disbursement.name,
loan_disbursement.disbursed_amount,
loan_disbursement.reference_number,
@@ -351,14 +372,33 @@ def get_ld_matching_query(bank_account, amount_condition, filters):
loan_disbursement.disbursed_amount <= filters.get('amount')
)
- vouchers = query.run(as_dict=1)
+ vouchers = query.run(as_list=True)
+
return vouchers
def get_lr_matching_query(bank_account, amount_condition, filters):
loan_repayment = frappe.qb.DocType("Loan Repayment")
+ matching_reference = loan_repayment.reference_number == filters.get("reference_number")
+ matching_party = loan_repayment.applicant_type == filters.get("party_type") and \
+ loan_repayment.applicant == filters.get("party")
+
+ rank = (
+ frappe.qb.terms.Case()
+ .when(matching_reference, 1)
+ .else_(0)
+ )
+
+ rank1 = (
+ frappe.qb.terms.Case()
+ .when(matching_party, 1)
+ .else_(0)
+ )
+
query = frappe.qb.from_(loan_repayment).select(
+ rank + rank1 + 1,
+ ConstantColumn("Loan Repayment").as_("doctype"),
loan_repayment.name,
- loan_repayment.paid_amount,
+ loan_repayment.amount_paid,
loan_repayment.reference_number,
loan_repayment.reference_date,
loan_repayment.applicant_type,
@@ -368,19 +408,20 @@ def get_lr_matching_query(bank_account, amount_condition, filters):
).where(
loan_repayment.clearance_date.isnull()
).where(
- loan_repayment.disbursement_account == bank_account
+ loan_repayment.payment_account == bank_account
)
if amount_condition:
query.where(
- loan_repayment.paid_amount == filters.get('amount')
+ loan_repayment.amount_paid == filters.get('amount')
)
else:
query.where(
- loan_repayment.paid_amount <= filters.get('amount')
+ loan_repayment.amount_paid <= filters.get('amount')
)
- vouchers = query.run(as_dict=1)
+ vouchers = query.run()
+
return vouchers
def get_pe_matching_query(amount_condition, account_from_to, transaction):
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 51e1d6e9a0..da944fa4ce 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -49,7 +49,8 @@ class BankTransaction(StatusUpdater):
def clear_linked_payment_entries(self, for_cancel=False):
for payment_entry in self.payment_entries:
- if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
+ if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim", "Loan Repayment",
+ "Loan Disbursement"]:
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
elif payment_entry.payment_document == "Sales Invoice":
@@ -104,6 +105,7 @@ def get_total_allocated_amount(payment_entry):
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
def get_paid_amount(payment_entry, currency, bank_account):
+ print(payment_entry.payment_document, "#@#@#@")
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
paid_amount_field = "paid_amount"
@@ -116,11 +118,18 @@ def get_paid_amount(payment_entry, currency, bank_account):
payment_entry.payment_entry, paid_amount_field)
elif payment_entry.payment_document == "Journal Entry":
- return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, "sum(credit_in_account_currency)")
+ return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account},
+ "sum(credit_in_account_currency)")
elif payment_entry.payment_document == "Expense Claim":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
+ elif payment_entry.payment_document == "Loan Disbursement":
+ return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "disbursed_amount")
+
+ elif payment_entry.payment_document == "Loan Repayment":
+ return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid")
+
else:
frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 766602de86..480e010b49 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -40,7 +40,7 @@
"repayment_details",
"amended_from",
"accounting_details_section",
- "repayment_account",
+ "payment_account",
"penalty_income_account",
"column_break_36",
"loan_account"
@@ -281,7 +281,7 @@
},
{
"fetch_from": "against_loan.payment_account",
- "fieldname": "repayment_account",
+ "fieldname": "payment_account",
"fieldtype": "Link",
"label": "Repayment Account",
"options": "Account",
@@ -311,7 +311,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2022-02-17 19:10:07.742298",
+ "modified": "2022-02-18 19:10:07.742298",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Repayment",
From 0b5e618e3ab206f7ae080f570a736a87fcbccf2d Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 21 Feb 2022 11:46:44 +0530
Subject: [PATCH 18/64] fix: Update bank reconciliation statement
---
.../bank_reconciliation_statement.py | 105 ++++++++++++++++--
1 file changed, 95 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 6c401fb8f3..b72d266977 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -4,7 +4,12 @@
import frappe
from frappe import _
-from frappe.utils import flt, getdate, nowdate
+from frappe.query_builder.custom import ConstantColumn
+from frappe.query_builder.functions import Sum
+from frappe.utils import flt, getdate
+from pypika import CustomFunction
+
+from erpnext.accounts.utils import get_balance_on
def execute(filters=None):
@@ -18,7 +23,6 @@ def execute(filters=None):
data = get_entries(filters)
- from erpnext.accounts.utils import get_balance_on
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
total_debit, total_credit = 0,0
@@ -118,7 +122,21 @@ def get_columns():
]
def get_entries(filters):
- journal_entries = frappe.db.sql("""
+ journal_entries = get_journal_entries(filters)
+
+ payment_entries = get_payment_entries(filters)
+
+ loan_entries = get_loan_entries(filters)
+
+ pos_entries = []
+ if filters.include_pos_transactions:
+ pos_entries = get_pos_entries(filters)
+
+ return sorted(list(payment_entries)+list(journal_entries+list(pos_entries) + list(loan_entries)),
+ key=lambda k: getdate(k['posting_date']))
+
+def get_journal_entries(filters):
+ return frappe.db.sql("""
select "Journal Entry" as payment_document, jv.posting_date,
jv.name as payment_entry, jvd.debit_in_account_currency as debit,
jvd.credit_in_account_currency as credit, jvd.against_account,
@@ -130,7 +148,8 @@ def get_entries(filters):
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
and ifnull(jv.is_opening, 'No') = 'No'""", filters, as_dict=1)
- payment_entries = frappe.db.sql("""
+def get_payment_entries(filters):
+ return frappe.db.sql("""
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no, reference_date as ref_date,
@@ -145,9 +164,8 @@ def get_entries(filters):
and ifnull(clearance_date, '4000-01-01') > %(report_date)s
""", filters, as_dict=1)
- pos_entries = []
- if filters.include_pos_transactions:
- pos_entries = frappe.db.sql("""
+def get_pos_entries(filters):
+ return frappe.db.sql("""
select
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
si.posting_date, si.debit_to as against_account, sip.clearance_date,
@@ -161,8 +179,42 @@ def get_entries(filters):
si.posting_date ASC, si.name DESC
""", filters, as_dict=1)
- return sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
- key=lambda k: k['posting_date'] or getdate(nowdate()))
+def get_loan_entries(filters):
+ loan_docs = []
+ for doctype in ["Loan Disbursement", "Loan Repayment"]:
+ loan_doc = frappe.qb.DocType(doctype)
+ ifnull = CustomFunction('IFNULL', ['value', 'default'])
+
+ if doctype == "Loan Disbursement":
+ amount_field = (loan_doc.disbursed_amount).as_("credit")
+ posting_date = (loan_doc.disbursement_date).as_("posting_date")
+ account = loan_doc.disbursement_account
+ else:
+ amount_field = (loan_doc.amount_paid).as_("debit")
+ posting_date = (loan_doc.posting_date).as_("posting_date")
+ account = loan_doc.payment_account
+
+ entries = frappe.qb.from_(loan_doc).select(
+ ConstantColumn(doctype).as_("payment_document"),
+ (loan_doc.name).as_("payment_entry"),
+ (loan_doc.reference_number).as_("reference_no"),
+ (loan_doc.reference_date).as_("ref_date"),
+ amount_field,
+ posting_date,
+ ).where(
+ loan_doc.docstatus == 1
+ ).where(
+ account == filters.get('account')
+ ).where(
+ posting_date <= getdate(filters.get('report_date'))
+ ).where(
+ ifnull(loan_doc.clearance_date, '4000-01-01') > getdate(filters.get('report_date'))
+ ).run(as_dict=1)
+
+ loan_docs.extend(entries)
+
+ return loan_docs
+
def get_amounts_not_reflected_in_system(filters):
je_amount = frappe.db.sql("""
@@ -182,7 +234,40 @@ def get_amounts_not_reflected_in_system(filters):
pe_amount = flt(pe_amount[0][0]) if pe_amount else 0.0
- return je_amount + pe_amount
+ loan_amount = get_loan_amount(filters)
+
+ return je_amount + pe_amount + loan_amount
+
+def get_loan_amount(filters):
+ total_amount = 0
+ for doctype in ["Loan Disbursement", "Loan Repayment"]:
+ loan_doc = frappe.qb.DocType(doctype)
+ ifnull = CustomFunction('IFNULL', ['value', 'default'])
+
+ if doctype == "Loan Disbursement":
+ amount_field = Sum(loan_doc.disbursed_amount)
+ posting_date = (loan_doc.disbursement_date).as_("posting_date")
+ account = loan_doc.disbursement_account
+ else:
+ amount_field = Sum(loan_doc.amount_paid)
+ posting_date = (loan_doc.posting_date).as_("posting_date")
+ account = loan_doc.payment_account
+
+ amount = frappe.qb.from_(loan_doc).select(
+ amount_field
+ ).where(
+ loan_doc.docstatus == 1
+ ).where(
+ account == filters.get('account')
+ ).where(
+ posting_date > getdate(filters.get('report_date'))
+ ).where(
+ ifnull(loan_doc.clearance_date, '4000-01-01') <= getdate(filters.get('report_date'))
+ ).run()[0][0]
+
+ total_amount += flt(amount)
+
+ return amount
def get_balance_row(label, amount, account_currency):
if amount > 0:
From c5808543c83ea43f62784331fb7c513543e454f0 Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Mon, 21 Feb 2022 12:41:08 +0530
Subject: [PATCH 19/64] fix(asset): no. of depreciation booked cannot be equal
to total no. of depreciations
---
erpnext/assets/doctype/asset/asset.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 6e87426ccb..ea473fa7bb 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -417,11 +417,12 @@ class Asset(AccountsController):
def validate_asset_finance_books(self, row):
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
frappe.throw(_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount")
- .format(row.idx))
+ .format(row.idx), title=_("Invalid Schedule"))
if not row.depreciation_start_date:
if not self.available_for_use_date:
- frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx))
+ frappe.throw(_("Row {0}: Depreciation Start Date is required")
+ .format(row.idx), title=_("Invalid Schedule"))
row.depreciation_start_date = get_last_day(self.available_for_use_date)
if not self.is_existing_asset:
@@ -439,8 +440,9 @@ class Asset(AccountsController):
else:
self.number_of_depreciations_booked = 0
- if cint(self.number_of_depreciations_booked) > cint(row.total_number_of_depreciations):
- frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations"))
+ if flt(row.total_number_of_depreciations) <= cint(self.number_of_depreciations_booked):
+ frappe.throw(_("Row {0}: Total Number of Depreciations cannot be less than or equal to Number of Depreciations Booked")
+ .format(row.idx), title=_("Invalid Schedule"))
if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.purchase_date):
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date")
From 780694f6e2d686ca7d037556a52e097802814266 Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Mon, 21 Feb 2022 12:45:52 +0530
Subject: [PATCH 20/64] test: number_of_depr_booked = total_number_of_depr
---
erpnext/assets/doctype/asset/test_asset.py | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index c08dc21a8f..ddbff89fc7 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -873,8 +873,9 @@ class TestDepreciationBasics(AssetSetup):
self.assertRaises(frappe.ValidationError, asset.save)
def test_number_of_depreciations(self):
- """Tests if an error is raised when number_of_depreciations_booked > total_number_of_depreciations."""
+ """Tests if an error is raised when number_of_depreciations_booked >= total_number_of_depreciations."""
+ # number_of_depreciations_booked > total_number_of_depreciations
asset = create_asset(
item_code = "Macbook Pro",
calculate_depreciation = 1,
@@ -889,6 +890,21 @@ class TestDepreciationBasics(AssetSetup):
self.assertRaises(frappe.ValidationError, asset.save)
+ # number_of_depreciations_booked = total_number_of_depreciations
+ asset_2 = create_asset(
+ item_code = "Macbook Pro",
+ calculate_depreciation = 1,
+ available_for_use_date = "2019-12-31",
+ total_number_of_depreciations = 5,
+ expected_value_after_useful_life = 10000,
+ depreciation_start_date = "2020-07-01",
+ opening_accumulated_depreciation = 10000,
+ number_of_depreciations_booked = 5,
+ do_not_save = 1
+ )
+
+ self.assertRaises(frappe.ValidationError, asset_2.save)
+
def test_depreciation_start_date_is_before_purchase_date(self):
asset = create_asset(
item_code = "Macbook Pro",
From 28cc2dbb72fc3d716ffcb19b039dccd67c13eb33 Mon Sep 17 00:00:00 2001
From: marination
Date: Mon, 21 Feb 2022 16:14:40 +0530
Subject: [PATCH 21/64] fix: Block merging items if both have product bundles
---
erpnext/stock/doctype/item/item.py | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index b9e8b3f2f1..d984d6eb99 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -398,6 +398,7 @@ class Item(Document):
if merge:
self.validate_properties_before_merge(new_name)
+ self.validate_duplicate_product_bundles_before_merge(old_name, new_name)
self.validate_duplicate_website_item_before_merge(old_name, new_name)
def after_rename(self, old_name, new_name, merge):
@@ -462,6 +463,18 @@ class Item(Document):
msg += ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list])
frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError)
+ def validate_duplicate_product_bundles_before_merge(self, old_name, new_name):
+ "Block merge if both old and new items have product bundles."
+ bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name})
+ if bundle:
+ bundle_link = get_link_to_form("Product Bundle", bundle)
+ old_name, new_name = frappe.bold(old_name), frappe.bold(new_name)
+
+ msg = _("Please delete Product Bundle {0}, before merging {1} into {2}").format(
+ bundle_link, old_name, new_name
+ )
+ frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError)
+
def validate_duplicate_website_item_before_merge(self, old_name, new_name):
"""
Block merge if both old and new items have website items against them.
@@ -479,8 +492,9 @@ class Item(Document):
old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0]
web_item_link = get_link_to_form("Website Item", old_web_item)
+ old_name, new_name = frappe.bold(old_name), frappe.bold(new_name)
- msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} and {new_name}"
+ msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} into {new_name}"
frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError)
def set_last_purchase_rate(self, new_name):
From 530f9f70291758d51babd7ec4f52eefe1a899ef1 Mon Sep 17 00:00:00 2001
From: marination
Date: Mon, 21 Feb 2022 16:48:04 +0530
Subject: [PATCH 22/64] test: Item Merging with Product Bundles
---
erpnext/stock/doctype/item/test_item.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index fd4df42187..6f5f1ff786 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -15,6 +15,7 @@ from erpnext.controllers.item_variant import (
get_variant,
)
from erpnext.stock.doctype.item.item import (
+ DataValidationError,
InvalidBarcode,
StockExistsForTemplate,
get_item_attribute,
@@ -388,6 +389,25 @@ class TestItem(ERPNextTestCase):
self.assertTrue(frappe.db.get_value("Bin",
{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))
+ def test_item_merging_with_product_bundle(self):
+ from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
+
+ create_item("Test Item Bundle Item 1", is_stock_item=False)
+ create_item("Test Item Bundle Item 2", is_stock_item=False)
+ create_item("Test Item inside Bundle")
+ bundle_items = ["Test Item inside Bundle"]
+
+ bundle1 = make_product_bundle("Test Item Bundle Item 1", bundle_items, qty=2)
+ make_product_bundle("Test Item Bundle Item 2", bundle_items, qty=2)
+
+ with self.assertRaises(DataValidationError):
+ frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True)
+
+ bundle1.delete()
+ frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True)
+
+ self.assertFalse(frappe.db.exists("Item", "Test Item Bundle Item 1"))
+
def test_uom_conversion_factor(self):
if frappe.db.exists('Item', 'Test Item UOM'):
frappe.delete_doc('Item', 'Test Item UOM')
From a4c6cb9f12f0ff931909a15b657b62a4bc85a20b Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 21 Feb 2022 17:08:25 +0530
Subject: [PATCH 23/64] fix: Remove print statements
---
erpnext/accounts/doctype/bank_transaction/bank_transaction.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index da944fa4ce..a476cab55f 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -105,7 +105,6 @@ def get_total_allocated_amount(payment_entry):
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
def get_paid_amount(payment_entry, currency, bank_account):
- print(payment_entry.payment_document, "#@#@#@")
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
paid_amount_field = "paid_amount"
From 87b59fc96c7bb37fcfbce097bd7c8184fce967ba Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Mon, 21 Feb 2022 22:53:29 +0530
Subject: [PATCH 24/64] fix(LMS): program enrollment does not give any feedback
(#29922)
---
erpnext/www/lms/macros/hero.html | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/erpnext/www/lms/macros/hero.html b/erpnext/www/lms/macros/hero.html
index e72bfc8175..95ba8f7df2 100644
--- a/erpnext/www/lms/macros/hero.html
+++ b/erpnext/www/lms/macros/hero.html
@@ -11,7 +11,7 @@
{% if frappe.session.user == 'Guest' %}
{{_('Sign Up')}}
{% elif not has_access %}
- {{_('Enroll')}}
+ {{_('Enroll')}}
{% endif %}
@@ -20,34 +20,35 @@
From 4738367d6407e9ffc22ba2c9ef1649573608be50 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Mon, 21 Feb 2022 22:54:46 +0530
Subject: [PATCH 25/64] fix: boarding task dates not set when activity begins
on is set to 0 (#29921)
---
.../employee_boarding_controller.py | 4 +--
.../test_employee_onboarding.py | 32 +++++++++++++------
.../doctype/salary_slip/test_salary_slip.py | 6 ++--
3 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/erpnext/controllers/employee_boarding_controller.py b/erpnext/controllers/employee_boarding_controller.py
index ae2c73758c..dd02ce1748 100644
--- a/erpnext/controllers/employee_boarding_controller.py
+++ b/erpnext/controllers/employee_boarding_controller.py
@@ -104,11 +104,11 @@ class EmployeeBoardingController(Document):
def get_task_dates(self, activity, holiday_list):
start_date = end_date = None
- if activity.begin_on:
+ if activity.begin_on is not None:
start_date = add_days(self.boarding_begins_on, activity.begin_on)
start_date = self.update_if_holiday(start_date, holiday_list)
- if activity.duration:
+ if activity.duration is not None:
end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration)
end_date = self.update_if_holiday(end_date, holiday_list)
diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
index 2d129c8acf..0fb821ddb2 100644
--- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
+++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
@@ -4,7 +4,7 @@
import unittest
import frappe
-from frappe.utils import getdate
+from frappe.utils import add_days, getdate
from erpnext.hr.doctype.employee_onboarding.employee_onboarding import (
IncompleteTaskError,
@@ -35,6 +35,15 @@ class TestEmployeeOnboarding(unittest.TestCase):
# boarding status
self.assertEqual(onboarding.boarding_status, 'Pending')
+ # start and end dates
+ start_date, end_date = frappe.db.get_value('Task', onboarding.activities[0].task, ['exp_start_date', 'exp_end_date'])
+ self.assertEqual(getdate(start_date), getdate(onboarding.boarding_begins_on))
+ self.assertEqual(getdate(end_date), add_days(start_date, onboarding.activities[0].duration))
+
+ start_date, end_date = frappe.db.get_value('Task', onboarding.activities[1].task, ['exp_start_date', 'exp_end_date'])
+ self.assertEqual(getdate(start_date), add_days(onboarding.boarding_begins_on, onboarding.activities[0].duration))
+ self.assertEqual(getdate(end_date), add_days(start_date, onboarding.activities[1].duration))
+
# complete the task
project = frappe.get_doc('Project', onboarding.project)
for task in frappe.get_all('Task', dict(project=project.name)):
@@ -57,10 +66,7 @@ class TestEmployeeOnboarding(unittest.TestCase):
self.assertEqual(employee.employee_name, 'Test Researcher')
def tearDown(self):
- for entry in frappe.get_all('Employee Onboarding'):
- doc = frappe.get_doc('Employee Onboarding', entry.name)
- doc.cancel()
- doc.delete()
+ frappe.db.rollback()
def get_job_applicant():
@@ -87,23 +93,31 @@ def get_job_offer(applicant_name):
def create_employee_onboarding():
applicant = get_job_applicant()
job_offer = get_job_offer(applicant.name)
- holiday_list = make_holiday_list()
+
+ holiday_list = make_holiday_list('_Test Employee Boarding')
+ holiday_list = frappe.get_doc('Holiday List', holiday_list)
+ holiday_list.holidays = []
+ holiday_list.save()
onboarding = frappe.new_doc('Employee Onboarding')
onboarding.job_applicant = applicant.name
onboarding.job_offer = job_offer.name
onboarding.date_of_joining = onboarding.boarding_begins_on = getdate()
onboarding.company = '_Test Company'
- onboarding.holiday_list = holiday_list
+ onboarding.holiday_list = holiday_list.name
onboarding.designation = 'Researcher'
onboarding.append('activities', {
'activity_name': 'Assign ID Card',
'role': 'HR User',
- 'required_for_employee_creation': 1
+ 'required_for_employee_creation': 1,
+ 'begin_on': 0,
+ 'duration': 1
})
onboarding.append('activities', {
'activity_name': 'Assign a laptop',
- 'role': 'HR User'
+ 'role': 'HR User',
+ 'begin_on': 1,
+ 'duration': 1
})
onboarding.status = 'Pending'
onboarding.insert()
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index daa0f8952b..6a5debf998 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -1019,13 +1019,13 @@ def setup_test():
frappe.db.set_value('HR Settings', None, 'leave_status_notification_template', None)
frappe.db.set_value('HR Settings', None, 'leave_approval_notification_template', None)
-def make_holiday_list():
+def make_holiday_list(holiday_list_name=None):
fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company())
- holiday_list = frappe.db.exists("Holiday List", "Salary Slip Test Holiday List")
+ holiday_list = frappe.db.exists("Holiday List", holiday_list_name or "Salary Slip Test Holiday List")
if not holiday_list:
holiday_list = frappe.get_doc({
"doctype": "Holiday List",
- "holiday_list_name": "Salary Slip Test Holiday List",
+ "holiday_list_name": holiday_list_name or "Salary Slip Test Holiday List",
"from_date": fiscal_year[1],
"to_date": fiscal_year[2],
"weekly_off": "Sunday"
From 70b960e650bbc1c418eecd14ac42d64a3103a43c Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 22 Feb 2022 09:16:08 +0530
Subject: [PATCH 26/64] fix: Account filter in PSOA
---
.../process_statement_of_accounts.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index 09aa72352e..1b34d6d1f2 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -73,7 +73,7 @@ def get_report_pdf(doc, consolidated=True):
'to_date': doc.to_date,
'company': doc.company,
'finance_book': doc.finance_book if doc.finance_book else None,
- 'account': doc.account if doc.account else None,
+ 'account': [doc.account] if doc.account else None,
'party_type': 'Customer',
'party': [entry.customer],
'presentation_currency': presentation_currency,
From d011a3f82c5cf9c1dc4fe0561194d47cff6099d0 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 22 Feb 2022 11:41:09 +0530
Subject: [PATCH 27/64] fix(Salary Slip): TypeError while clearing any amount
field in components (#29931)
---
erpnext/payroll/doctype/salary_slip/salary_slip.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index f727ff4378..d2a39989a6 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -1268,7 +1268,7 @@ class SalarySlip(TransactionBase):
for i, earning in enumerate(self.earnings):
if earning.salary_component == salary_component:
self.earnings[i].amount = wages_amount
- self.gross_pay += self.earnings[i].amount
+ self.gross_pay += flt(self.earnings[i].amount, earning.precision("amount"))
self.net_pay = flt(self.gross_pay) - flt(self.total_deduction)
def compute_year_to_date(self):
From 235fc127b3ecf943176ed9c208425f9bda100798 Mon Sep 17 00:00:00 2001
From: Marica
Date: Tue, 22 Feb 2022 12:53:46 +0530
Subject: [PATCH 28/64] fix: Fetch conversion factor even if it already existed
in row, on item change (#29917)
* fix: Fetch conversion factor even if it already existed in row, on item change
* fix: Retain manually changed conversion factor
- If item code changes, reset conversion factor on client side
- Keep API behavious consistent, if conversion factor is sent, same must come back
- API should not ideally reset values in most cases
---
erpnext/public/js/controllers/transaction.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 933ced0bd7..ae8c0c8c6d 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -525,6 +525,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
item.weight_per_unit = 0;
item.weight_uom = '';
+ item.conversion_factor = 0;
if(['Sales Invoice'].includes(this.frm.doc.doctype)) {
update_stock = cint(me.frm.doc.update_stock);
From 7f55226a5807645db4f93c8038f1cc03a6fc0ce6 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Tue, 22 Feb 2022 16:55:43 +0530
Subject: [PATCH 29/64] fix: remove customer field value when MR is not
customer provided (#29938)
---
.../stock/doctype/material_request/material_request.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index b39328f85b..51209acb27 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -56,14 +56,13 @@ class MaterialRequest(BuyingController):
if actual_so_qty and (flt(so_items[so_no][item]) + already_indented > actual_so_qty):
frappe.throw(_("Material Request of maximum {0} can be made for Item {1} against Sales Order {2}").format(actual_so_qty - already_indented, item, so_no))
- # Validate
- # ---------------------
def validate(self):
super(MaterialRequest, self).validate()
self.validate_schedule_date()
self.check_for_on_hold_or_closed_status('Sales Order', 'sales_order')
self.validate_uom_is_integer("uom", "qty")
+ self.validate_material_request_type()
if not self.status:
self.status = "Draft"
@@ -83,6 +82,12 @@ class MaterialRequest(BuyingController):
self.reset_default_field_value("set_warehouse", "items", "warehouse")
self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
+ def validate_material_request_type(self):
+ """ Validate fields in accordance with selected type """
+
+ if self.material_request_type != "Customer Provided":
+ self.customer = None
+
def set_title(self):
'''Set title as comma separated list of items'''
if not self.title:
From 745f7bc5f0fd014dcc837c41e2058be91166e1b4 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Tue, 22 Feb 2022 17:03:11 +0530
Subject: [PATCH 30/64] docs: add human readable specifications for stock
ledger (#29308)
* docs: add human readable specifications for stock ledger
* docs: reposting technical implementation notes
---
erpnext/stock/spec/README.md | 103 ++++++++++++++++++++++++++++++++
erpnext/stock/spec/reposting.md | 38 ++++++++++++
2 files changed, 141 insertions(+)
create mode 100644 erpnext/stock/spec/README.md
create mode 100644 erpnext/stock/spec/reposting.md
diff --git a/erpnext/stock/spec/README.md b/erpnext/stock/spec/README.md
new file mode 100644
index 0000000000..f5a3501fe4
--- /dev/null
+++ b/erpnext/stock/spec/README.md
@@ -0,0 +1,103 @@
+# Implementation notes for Stock Ledger
+
+
+## Important files
+
+- `stock/stock_ledger.py`
+- `controllers/stock_controller.py`
+- `stock/valuation.py`
+
+## What is in an Stock Ledger Entry (SLE)?
+
+Stock Ledger Entry is a single row in the Stock Ledger. It signifies some
+modification of stock for a particular Item in the specified warehouse.
+
+- `item_code`: item for which ledger entry is made
+- `warehouse`: warehouse where inventory is affected
+- `actual_qty`: change in qty
+- `qty_after_transaction`: quantity available after the transaction is processed
+- `incoming_rate`: rate at which inventory was received.
+- `is_cancelled`: if 1 then stock ledger entry is cancelled and should not be used
+for any business logic except for the code that handles cancellation.
+- `posting_date` & `posting_time`: Specify the temporal ordering of stock ledger
+ entries. Ties are broken by `creation` timestamp.
+- `voucher_type`: Many transaction can create SLE, e.g. Stock Entry, Purchase
+ Invoice
+- `voucher_no`: `name` of the transaction that created SLE
+- `voucher_detail_no`: `name` of the child table row from parent transaction
+ that created the SLE.
+- `dependant_sle_voucher_detail_no`: cross-warehouse transfers need this
+ reference in order to update dependent warehouse rates in case of change in
+ rate.
+- `recalculate_rate`: if this is checked in/out rates are recomputed on
+ transactions.
+- `valuation_rate`: current average valuation rate.
+- `stock_value`: current total stock value
+- `stock_value_difference`: stock value difference made between last and current
+ entry. This value is booked in accounting ledger.
+- `stock_queue`: if FIFO/LIFO is used this represents queue/stack maintained for
+ computing incoming rate for inventory getting consumed.
+- `batch_no`: batch no for which stock entry is made; each stock entry can only
+ affect one batch number.
+- `serial_no`: newline separated list of serial numbers that were added (if
+ actual_qty > 0) or else removed. Currently multiple serial nos can have single
+ SLE but this will likely change in future.
+
+
+## Implementation of Stock Ledger
+
+Stock Ledger Entry affects stock of combinations of (item_code, warehouse) and
+optionally batch no if specified. For simplicity, lets avoid batch no. for now.
+
+
+Stock Ledger Entry table stores stock ledger for all combinations of item_code
+and warehouse. So whenever any operations are to be performed on said
+item-warehouse combination stock ledger is filtered and sorted by posting
+datetime. A typical query that will give you individual ledger looks like this:
+
+```sql
+select *
+from `tabStock Ledger Entry` as sle
+where
+ is_cancelled = 0 --- cancelled entries don't affect ledger
+ and item_code = 'item_code' and warehouse = 'warehouse_name'
+order by timestamp(posting_date, posting_time), creation
+```
+
+New entry is just an update to the last entry which is found by looking at last
+row in the filter ledger.
+
+
+### Serial nos
+
+Serial numbers do not follow any valuation method configuration and they are
+consumed at rate they were produced unless they are grouped in which case they
+are consumed at weighted average rate.
+
+
+### Batch Nos
+
+Batches are currently NOT consumed as per batch wise valuation rate, instead
+global FIFO queue for the item is used for valuation rate.
+
+
+## Creation process of SLEs
+
+- SLE creation is usually triggered by Stock Transactions using a method
+ conventionally named `update_stock_ledger()` This might not be defined for
+ stock transaction and could be specified somewhere in inheritance hierarchy of
+ controllers.
+- This method produces SLE objects which are processed by `make_sl_entries` in
+ `stock_ledger.py` which commits the SLE to database.
+- `update_entries_after` class is used to process ONLY the inserted SLE's queue
+ and valuation.
+- The change in qty is propagated to future entries immediately. Valuation and
+ queue for future entries is processed in background using repost item
+ valuation.
+
+
+## Accounting impact
+
+- Accounting impact for stock transaction is handled by `get_gl_entries()`
+ method on controllers. Each transaction has different business logic for
+ booking the accounting impact.
diff --git a/erpnext/stock/spec/reposting.md b/erpnext/stock/spec/reposting.md
new file mode 100644
index 0000000000..b0d59fe9bb
--- /dev/null
+++ b/erpnext/stock/spec/reposting.md
@@ -0,0 +1,38 @@
+# Stock Reposting
+
+Stock "reposting" is process of re-processing Stock Ledger Entry and GL Entries
+in event of backdated stock transaction.
+
+*Backdated stock transaction*: Any stock transaction for which some
+item-warehouse combination has a future transactions.
+
+## Why is this required?
+Stock Ledger is stateful, it maintains queue, qty at any
+point in time. So if you do a backdated transaction all future values change,
+queues need to be re-evaluated etc. Watch Nabin and Rohit's conference
+presentation for explanation: https://www.youtube.com/watch?v=mw3WAnekGIM
+
+## How is this implemented?
+Whenever backdated transaction is detected, instead of
+fully processing it while submitting, the processing is queued using "Repost
+Item Valuation" doctype. Every hour a scheduled job runs and processes this
+queue (for up to maximum of 25 minutes)
+
+
+## Queue implementation
+- "Repost item valuation" (RIV) is automatically submitted from backdated transactions. (check stock_controller.py)
+- Draft and cancelled RIV are ignored.
+- Keep filter of "submitted" documents when doing anything with RIVs.
+- The default status is "Queued".
+- When background job runs, it picks the oldest pending reposts and changes the status to "In Progress" and when it finishes it
+changes to "Completed"
+- There are two more status: "Failed" when reposting failed and "Skipped" when reposting is deemed not necessary so it's skipped.
+- technical detail: Entry point for whole process is "repost_entries" function in repost_item_valuation.py
+
+
+## How to identify broken stock data:
+There are 4 major reports for checking broken stock data:
+- Incorrect balance qty after the transaction - to check if the running total of qty isn't correct.
+- Incorrect stock value report - to check incorrect value books in accounts for stock transactions
+- Incorrect serial no valuation -specific to serial nos
+- Stock ledger invariant check - combined report for checking qty, running total, queue, balance value etc
From 1682a26fe69b9b3fa64293e692e79a553b842ca2 Mon Sep 17 00:00:00 2001
From: Subin Tom
Date: Tue, 22 Feb 2022 17:20:48 +0530
Subject: [PATCH 31/64] fix: Taxjar minor fixes
---
.../taxjar_integration.py | 46 +++++++++++--------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py
index a4e21579e3..14c86d5632 100644
--- a/erpnext/erpnext_integrations/taxjar_integration.py
+++ b/erpnext/erpnext_integrations/taxjar_integration.py
@@ -8,10 +8,6 @@ from frappe.utils import cint, flt
from erpnext import get_default_company, get_region
-TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
-SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head")
-TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
-TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax")
SUPPORTED_COUNTRY_CODES = ["AT", "AU", "BE", "BG", "CA", "CY", "CZ", "DE", "DK", "EE", "ES", "FI",
"FR", "GB", "GR", "HR", "HU", "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PL", "PT", "RO",
"SE", "SI", "SK", "US"]
@@ -35,12 +31,14 @@ def get_client():
if api_key and api_url:
client = taxjar.Client(api_key=api_key, api_url=api_url)
client.set_api_config('headers', {
- 'x-api-version': '2020-08-07'
+ 'x-api-version': '2022-01-24'
})
return client
def create_transaction(doc, method):
+ TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
+
"""Create an order transaction in TaxJar"""
if not TAXJAR_CREATE_TRANSACTIONS:
@@ -51,6 +49,7 @@ def create_transaction(doc, method):
if not client:
return
+ TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
sales_tax = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == TAX_ACCOUNT_HEAD])
if not sales_tax:
@@ -79,6 +78,7 @@ def create_transaction(doc, method):
def delete_transaction(doc, method):
"""Delete an existing TaxJar order transaction"""
+ TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
if not TAXJAR_CREATE_TRANSACTIONS:
return
@@ -92,6 +92,8 @@ def delete_transaction(doc, method):
def get_tax_data(doc):
+ SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head")
+
from_address = get_company_address_details(doc)
from_shipping_state = from_address.get("state")
from_country_code = frappe.db.get_value("Country", from_address.country, "code")
@@ -113,20 +115,20 @@ def get_tax_data(doc):
to_shipping_state = get_state_code(to_address, 'Shipping')
tax_dict = {
- 'from_country': from_country_code,
- 'from_zip': from_address.pincode,
- 'from_state': from_shipping_state,
- 'from_city': from_address.city,
- 'from_street': from_address.address_line1,
- 'to_country': to_country_code,
- 'to_zip': to_address.pincode,
- 'to_city': to_address.city,
- 'to_street': to_address.address_line1,
- 'to_state': to_shipping_state,
- 'shipping': shipping,
- 'amount': doc.net_total,
- 'plugin': 'erpnext',
- 'line_items': line_items
+ "from_country": from_country_code,
+ "from_zip": from_address.pincode,
+ "from_state": from_shipping_state,
+ "from_city": from_address.city,
+ "from_street": from_address.address_line1,
+ "to_country": to_country_code,
+ "to_zip": to_address.pincode,
+ "to_city": to_address.city,
+ "to_street": to_address.address_line1,
+ "to_state": to_shipping_state,
+ "shipping": shipping,
+ "amount": doc.net_total,
+ "plugin": "erpnext",
+ "line_items": line_items
}
return tax_dict
@@ -156,6 +158,9 @@ def get_line_item_dict(item, docstatus):
return tax_dict
def set_sales_tax(doc, method):
+ TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
+ TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax")
+
if not TAXJAR_CALCULATE_TAX:
return
@@ -206,6 +211,7 @@ def set_sales_tax(doc, method):
doc.run_method("calculate_taxes_and_totals")
def check_for_nexus(doc, tax_dict):
+ TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
if not frappe.db.get_value('TaxJar Nexus', {'region_code': tax_dict["to_state"]}):
for item in doc.get("items"):
item.tax_collectable = flt(0)
@@ -218,6 +224,8 @@ def check_for_nexus(doc, tax_dict):
def check_sales_tax_exemption(doc):
# if the party is exempt from sales tax, then set all tax account heads to zero
+ TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
+
sales_tax_exempted = hasattr(doc, "exempt_from_sales_tax") and doc.exempt_from_sales_tax \
or frappe.db.has_column("Customer", "exempt_from_sales_tax") \
and frappe.db.get_value("Customer", doc.customer, "exempt_from_sales_tax")
From 5d403449bdcbe514c33b8807b674fd23ba24d93a Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Tue, 22 Feb 2022 19:24:49 +0530
Subject: [PATCH 32/64] test: move report tests to subttest (#29945)
Basically failfast=False but for sub-tests
---
erpnext/accounts/test/test_reports.py | 15 ++++++++-------
erpnext/manufacturing/report/test_reports.py | 15 ++++++++-------
erpnext/stock/report/test_reports.py | 15 ++++++++-------
3 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/erpnext/accounts/test/test_reports.py b/erpnext/accounts/test/test_reports.py
index 78c109ab94..4ed966dcb9 100644
--- a/erpnext/accounts/test/test_reports.py
+++ b/erpnext/accounts/test/test_reports.py
@@ -39,10 +39,11 @@ class TestReports(unittest.TestCase):
def test_execute_all_accounts_reports(self):
"""Test that all script report in stock modules are executable with supported filters"""
for report, filter in REPORT_FILTER_TEST_CASES:
- execute_script_report(
- report_name=report,
- module="Accounts",
- filters=filter,
- default_filters=DEFAULT_FILTERS,
- optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
- )
+ with self.subTest(report=report):
+ execute_script_report(
+ report_name=report,
+ module="Accounts",
+ filters=filter,
+ default_filters=DEFAULT_FILTERS,
+ optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
+ )
diff --git a/erpnext/manufacturing/report/test_reports.py b/erpnext/manufacturing/report/test_reports.py
index 9f51ded6c7..e436fdca64 100644
--- a/erpnext/manufacturing/report/test_reports.py
+++ b/erpnext/manufacturing/report/test_reports.py
@@ -55,10 +55,11 @@ class TestManufacturingReports(unittest.TestCase):
def test_execute_all_manufacturing_reports(self):
"""Test that all script report in manufacturing modules are executable with supported filters"""
for report, filter in REPORT_FILTER_TEST_CASES:
- execute_script_report(
- report_name=report,
- module="Manufacturing",
- filters=filter,
- default_filters=DEFAULT_FILTERS,
- optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
- )
+ with self.subTest(report=report):
+ execute_script_report(
+ report_name=report,
+ module="Manufacturing",
+ filters=filter,
+ default_filters=DEFAULT_FILTERS,
+ optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
+ )
diff --git a/erpnext/stock/report/test_reports.py b/erpnext/stock/report/test_reports.py
index 525af40b41..76c20798bf 100644
--- a/erpnext/stock/report/test_reports.py
+++ b/erpnext/stock/report/test_reports.py
@@ -73,10 +73,11 @@ class TestReports(unittest.TestCase):
def test_execute_all_stock_reports(self):
"""Test that all script report in stock modules are executable with supported filters"""
for report, filter in REPORT_FILTER_TEST_CASES:
- execute_script_report(
- report_name=report,
- module="Stock",
- filters=filter,
- default_filters=DEFAULT_FILTERS,
- optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
- )
+ with self.subTest(report=report):
+ execute_script_report(
+ report_name=report,
+ module="Stock",
+ filters=filter,
+ default_filters=DEFAULT_FILTERS,
+ optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
+ )
From a61790c00fa2b3c53ba49d930c7d08b3f0213b65 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 22 Feb 2022 20:58:10 +0530
Subject: [PATCH 33/64] fix: Remove unintended changes
---
erpnext/controllers/accounts_controller.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 7913a39329..a94af10cde 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1954,7 +1954,8 @@ def update_bin_on_delete(row, doctype):
qty_dict["ordered_qty"] = get_ordered_qty(row.item_code, row.warehouse)
- update_bin_qty(row.item_code, row.warehouse, qty_dict)
+ if row.warehouse:
+ update_bin_qty(row.item_code, row.warehouse, qty_dict)
def validate_and_delete_children(parent, data):
deleted_children = []
From b0a1cd6a7bd9f0900d6f723c3b2cbf9037989fcc Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 23 Feb 2022 00:13:44 +0530
Subject: [PATCH 34/64] chore: Change heart icon to `icon-heart` and change var
`icon-stroke` to accomodate changes in frappe icon
- `icon-heart` got a stroke colour that needs to be overriden via var `icon-stroke
- Use `icon-heart` instead of `icon-heart-active` as the latter has a color fill now
---
erpnext/public/scss/shopping_cart.scss | 8 ++++----
erpnext/templates/includes/navbar/navbar_items.html | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
index 4b645b9dde..666043b219 100644
--- a/erpnext/public/scss/shopping_cart.scss
+++ b/erpnext/public/scss/shopping_cart.scss
@@ -338,14 +338,14 @@ body.product-page {
.btn-add-to-wishlist {
svg use {
- stroke: #F47A7A;
+ --icon-stroke: #F47A7A;
}
}
.btn-view-in-wishlist {
svg use {
fill: #F47A7A;
- stroke: none;
+ --icon-stroke: none;
}
}
@@ -1022,7 +1022,7 @@ body.product-page {
.not-wished {
cursor: pointer;
- stroke: #F47A7A !important;
+ --icon-stroke: #F47A7A !important;
&:hover {
fill: #F47A7A;
@@ -1030,7 +1030,7 @@ body.product-page {
}
.wished {
- stroke: none;
+ --icon-stroke: none;
fill: #F47A7A !important;
}
diff --git a/erpnext/templates/includes/navbar/navbar_items.html b/erpnext/templates/includes/navbar/navbar_items.html
index 327552117b..d7adae562e 100644
--- a/erpnext/templates/includes/navbar/navbar_items.html
+++ b/erpnext/templates/includes/navbar/navbar_items.html
@@ -13,7 +13,7 @@
-
+
From 714325071fd526b653266a52057177fa541764c2 Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 23 Feb 2022 00:15:39 +0530
Subject: [PATCH 35/64] fix: Remove accidental `as_dict` in frappe.db.get_all
---
erpnext/www/shop-by-category/index.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/erpnext/www/shop-by-category/index.py b/erpnext/www/shop-by-category/index.py
index 394621272b..09f97ba5ef 100644
--- a/erpnext/www/shop-by-category/index.py
+++ b/erpnext/www/shop-by-category/index.py
@@ -62,8 +62,7 @@ def get_category_records(categories):
"parent_item_group": "All Item Groups",
"show_in_website": 1
},
- fields=["name", "parent_item_group", "is_group", "image", "route"],
- as_dict=True
+ fields=["name", "parent_item_group", "is_group", "image", "route"]
)
else:
doctype = frappe.unscrub(category)
@@ -71,7 +70,7 @@ def get_category_records(categories):
if frappe.get_meta(doctype, cached=True).get_field("image"):
fields += ["image"]
- categorical_data[category] = frappe.db.get_all(doctype, fields=fields, as_dict=True)
+ categorical_data[category] = frappe.db.get_all(doctype, fields=fields)
return categorical_data
From aaa84a21ba8c1749735c6510c5f311c3db505aef Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Wed, 23 Feb 2022 10:54:44 +0530
Subject: [PATCH 36/64] fix: Email translations
---
erpnext/translations/de.csv | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index f345a87d03..b882b9d3c1 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -3731,7 +3731,7 @@ Earliest Age,Frühestes Alter,
Edit Details,Details bearbeiten,
Edit Profile,Profil bearbeiten,
Either GST Transporter ID or Vehicle No is required if Mode of Transport is Road,Bei Straßentransport ist entweder die GST-Transporter-ID oder die Fahrzeug-Nr. Erforderlich,
-Email,Email,
+Email,E-Mail,
Email Campaigns,E-Mail-Kampagnen,
Employee ID is linked with another instructor,Die Mitarbeiter-ID ist mit einem anderen Ausbilder verknüpft,
Employee Tax and Benefits,Mitarbeitersteuern und -leistungen,
@@ -6487,7 +6487,7 @@ Select Users,Wählen Sie Benutzer aus,
Send Emails At,Die E-Mails senden um,
Reminder,Erinnerung,
Daily Work Summary Group User,Tägliche Arbeit Zusammenfassung Gruppenbenutzer,
-email,Email,
+email,E-Mail,
Parent Department,Elternabteilung,
Leave Block List,Urlaubssperrenliste,
Days for which Holidays are blocked for this department.,"Tage, an denen eine Urlaubssperre für diese Abteilung gilt.",
From bf8743713dcb318958c01e693c6d1071fd5fc218 Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 23 Feb 2022 14:03:48 +0530
Subject: [PATCH 37/64] chore: Rollback after each test, due to premature
commit via `remove_user_permission`
- `remove_user_permission` in `test_warehouse_user` calls delete_doc that enqueues dynamic link deletion
- Execution of background job eventually commits
- While in the test suite it runs sequentially in the same thread and commits whatever was done until then
- Which is why the rollback in `tearDownClass` is quite useless here
- This premature commit causes many illegal transactions caught by `assertRaises` to be committed in the db
- This creates faulty/dirty ledgers and breaks reports, as outiside the test suite this shouldn't/wouldn't happen
- Rollback after each test, and for `test_warehouse_user` in particular, manually cancel transaction
---
erpnext/stock/doctype/stock_entry/test_stock_entry.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 6c6513beff..7ab41418ae 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -44,6 +44,7 @@ def get_sle(**args):
class TestStockEntry(ERPNextTestCase):
def tearDown(self):
+ frappe.db.rollback()
frappe.set_user("Administrator")
frappe.db.set_value("Manufacturing Settings", None, "material_consumption", "0")
@@ -565,6 +566,7 @@ class TestStockEntry(ERPNextTestCase):
st1.set_stock_entry_type()
st1.insert()
st1.submit()
+ st1.cancel()
frappe.set_user("Administrator")
remove_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com")
@@ -1023,13 +1025,10 @@ class TestStockEntry(ERPNextTestCase):
# Check if FG cost is calculated based on RM total cost
# RM total cost = 200, FG rate = 200/4(FG qty) = 50
- self.assertEqual(se.items[1].basic_rate, 50)
+ self.assertEqual(se.items[1].basic_rate, flt(se.items[0].basic_rate/4))
self.assertEqual(se.value_difference, 0.0)
self.assertEqual(se.total_incoming_value, se.total_outgoing_value)
- # teardown
- se.delete()
-
@change_settings("Stock Settings", {"allow_negative_stock": 0})
def test_future_negative_sle(self):
# Initialize item, batch, warehouse, opening qty
From 9c7df2eec5a4c53545e43cae8a9cd5d9dda1a029 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Tue, 22 Feb 2022 20:53:19 +0530
Subject: [PATCH 38/64] fix: ignore duplicates explicitly
---
.../bank_transaction/test_bank_transaction.py | 14 +-
.../report/tax_detail/test_tax_detail.py | 2 +-
erpnext/accounts/utils.py | 2 +-
erpnext/assets/doctype/asset/test_asset.py | 4 +-
.../asset_category/test_asset_category.py | 2 +-
.../buying/doctype/supplier/test_supplier.py | 227 +++++++++---------
.../shopping_cart/test_shopping_cart.py | 2 +-
.../tally_migration/tally_migration.py | 2 +-
erpnext/hr/doctype/employee/employee.py | 2 +-
.../doctype/exit_interview/exit_interview.py | 2 +-
.../doctype/vehicle_log/test_vehicle_log.py | 2 +-
.../homepage_section/test_homepage_section.py | 2 +-
erpnext/regional/india/setup.py | 5 +-
erpnext/setup/utils.py | 2 +-
erpnext/stock/doctype/batch/test_batch.py | 7 +-
15 files changed, 136 insertions(+), 141 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index 72b6893faf..d84b8e07d3 100644
--- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
@@ -109,7 +109,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
frappe.get_doc({
"doctype": "Bank",
"bank_name":bank_name,
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -119,7 +119,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
"account_name":"Checking Account",
"bank": bank_name,
"account": account_name
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -184,7 +184,7 @@ def add_vouchers():
"supplier_group":"All Supplier Groups",
"supplier_type": "Company",
"supplier_name": "Conrad Electronic"
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -203,7 +203,7 @@ def add_vouchers():
"supplier_group":"All Supplier Groups",
"supplier_type": "Company",
"supplier_name": "Mr G"
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -227,7 +227,7 @@ def add_vouchers():
"supplier_group":"All Supplier Groups",
"supplier_type": "Company",
"supplier_name": "Poore Simon's"
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -237,7 +237,7 @@ def add_vouchers():
"customer_group":"All Customer Groups",
"customer_type": "Company",
"customer_name": "Poore Simon's"
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -266,7 +266,7 @@ def add_vouchers():
"customer_group":"All Customer Groups",
"customer_type": "Company",
"customer_name": "Fayva"
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index bf668ab779..621de825ea 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -61,7 +61,7 @@ class TestTaxDetail(unittest.TestCase):
# Create GL Entries:
db_doc.submit()
else:
- db_doc.insert()
+ db_doc.insert(ignore_if_duplicate=True)
except frappe.exceptions.DuplicateEntryError:
pass
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 39e84e3cef..b17b90ba6e 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -847,7 +847,7 @@ def create_payment_gateway_account(gateway, payment_channel="Email"):
"payment_account": bank_account.name,
"currency": bank_account.account_currency,
"payment_channel": payment_channel
- }).insert(ignore_permissions=True)
+ }).insert(ignore_permissions=True, ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
# already exists, due to a reinstall?
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index ddbff89fc7..ffd1065efc 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -1280,7 +1280,7 @@ def create_asset(**args):
if not args.do_not_save:
try:
- asset.save()
+ asset.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -1321,7 +1321,7 @@ def create_fixed_asset_item(item_code=None, auto_create_assets=1, is_grouped_ass
"is_grouped_asset": is_grouped_asset,
"asset_naming_series": naming_series
})
- item.insert()
+ item.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
return item
diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py
index 3d19fa39d1..2f52248edb 100644
--- a/erpnext/assets/doctype/asset_category/test_asset_category.py
+++ b/erpnext/assets/doctype/asset_category/test_asset_category.py
@@ -23,7 +23,7 @@ class TestAssetCategory(unittest.TestCase):
})
try:
- asset_category.insert()
+ asset_category.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
diff --git a/erpnext/buying/doctype/supplier/test_supplier.py b/erpnext/buying/doctype/supplier/test_supplier.py
index 13fe9df13e..0fb81b2578 100644
--- a/erpnext/buying/doctype/supplier/test_supplier.py
+++ b/erpnext/buying/doctype/supplier/test_supplier.py
@@ -14,151 +14,150 @@ test_records = frappe.get_test_records('Supplier')
class TestSupplier(unittest.TestCase):
- def test_get_supplier_group_details(self):
- doc = frappe.new_doc("Supplier Group")
- doc.supplier_group_name = "_Testing Supplier Group"
- doc.payment_terms = "_Test Payment Term Template 3"
- doc.accounts = []
- test_account_details = {
- "company": "_Test Company",
- "account": "Creditors - _TC",
- }
- doc.append("accounts", test_account_details)
- doc.save()
- s_doc = frappe.new_doc("Supplier")
- s_doc.supplier_name = "Testing Supplier"
- s_doc.supplier_group = "_Testing Supplier Group"
- s_doc.payment_terms = ""
- s_doc.accounts = []
- s_doc.insert()
- s_doc.get_supplier_group_details()
- self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3")
- self.assertEqual(s_doc.accounts[0].company, "_Test Company")
- self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC")
- s_doc.delete()
- doc.delete()
+ def test_get_supplier_group_details(self):
+ doc = frappe.new_doc("Supplier Group")
+ doc.supplier_group_name = "_Testing Supplier Group"
+ doc.payment_terms = "_Test Payment Term Template 3"
+ doc.accounts = []
+ test_account_details = {
+ "company": "_Test Company",
+ "account": "Creditors - _TC",
+ }
+ doc.append("accounts", test_account_details)
+ doc.save()
+ s_doc = frappe.new_doc("Supplier")
+ s_doc.supplier_name = "Testing Supplier"
+ s_doc.supplier_group = "_Testing Supplier Group"
+ s_doc.payment_terms = ""
+ s_doc.accounts = []
+ s_doc.insert()
+ s_doc.get_supplier_group_details()
+ self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3")
+ self.assertEqual(s_doc.accounts[0].company, "_Test Company")
+ self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC")
+ s_doc.delete()
+ doc.delete()
- def test_supplier_default_payment_terms(self):
- # Payment Term based on Days after invoice date
- frappe.db.set_value(
- "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 3")
+ def test_supplier_default_payment_terms(self):
+ # Payment Term based on Days after invoice date
+ frappe.db.set_value(
+ "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 3")
- due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2016-02-21")
+ due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2016-02-21")
- due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2017-02-21")
+ due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2017-02-21")
- # Payment Term based on last day of month
- frappe.db.set_value(
- "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 1")
+ # Payment Term based on last day of month
+ frappe.db.set_value(
+ "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 1")
- due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2016-02-29")
+ due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2016-02-29")
- due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2017-02-28")
+ due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2017-02-28")
- frappe.db.set_value("Supplier", "_Test Supplier With Template 1", "payment_terms", "")
+ frappe.db.set_value("Supplier", "_Test Supplier With Template 1", "payment_terms", "")
- # Set credit limit for the supplier group instead of supplier and evaluate the due date
- frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 3")
+ # Set credit limit for the supplier group instead of supplier and evaluate the due date
+ frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 3")
- due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2016-02-21")
+ due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2016-02-21")
- # Payment terms for Supplier Group instead of supplier and evaluate the due date
- frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 1")
+ # Payment terms for Supplier Group instead of supplier and evaluate the due date
+ frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 1")
- # Leap year
- due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2016-02-29")
- # # Non Leap year
- due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
- self.assertEqual(due_date, "2017-02-28")
+ # Leap year
+ due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2016-02-29")
+ # # Non Leap year
+ due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
+ self.assertEqual(due_date, "2017-02-28")
- # Supplier with no default Payment Terms Template
- frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "")
- frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "")
+ # Supplier with no default Payment Terms Template
+ frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "")
+ frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "")
- due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier")
- self.assertEqual(due_date, "2016-01-22")
- # # Non Leap year
- due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier")
- self.assertEqual(due_date, "2017-01-22")
+ due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier")
+ self.assertEqual(due_date, "2016-01-22")
+ # # Non Leap year
+ due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier")
+ self.assertEqual(due_date, "2017-01-22")
- def test_supplier_disabled(self):
- make_test_records("Item")
+ def test_supplier_disabled(self):
+ make_test_records("Item")
- frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1)
+ frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1)
- from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
+ from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
- po = create_purchase_order(do_not_save=True)
+ po = create_purchase_order(do_not_save=True)
- self.assertRaises(PartyDisabled, po.save)
+ self.assertRaises(PartyDisabled, po.save)
- frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0)
+ frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0)
- po.save()
+ po.save()
- def test_supplier_country(self):
- # Test that country field exists in Supplier DocType
- supplier = frappe.get_doc('Supplier', '_Test Supplier with Country')
- self.assertTrue('country' in supplier.as_dict())
+ def test_supplier_country(self):
+ # Test that country field exists in Supplier DocType
+ supplier = frappe.get_doc('Supplier', '_Test Supplier with Country')
+ self.assertTrue('country' in supplier.as_dict())
- # Test if test supplier field record is 'Greece'
- self.assertEqual(supplier.country, "Greece")
+ # Test if test supplier field record is 'Greece'
+ self.assertEqual(supplier.country, "Greece")
- # Test update Supplier instance country value
- supplier = frappe.get_doc('Supplier', '_Test Supplier')
- supplier.country = 'Greece'
- supplier.save()
- self.assertEqual(supplier.country, "Greece")
+ # Test update Supplier instance country value
+ supplier = frappe.get_doc('Supplier', '_Test Supplier')
+ supplier.country = 'Greece'
+ supplier.save()
+ self.assertEqual(supplier.country, "Greece")
- def test_party_details_tax_category(self):
- from erpnext.accounts.party import get_party_details
+ def test_party_details_tax_category(self):
+ from erpnext.accounts.party import get_party_details
- frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing")
+ frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing")
- # Tax Category without Address
- details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
- self.assertEqual(details.tax_category, "_Test Tax Category 1")
+ # Tax Category without Address
+ details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
+ self.assertEqual(details.tax_category, "_Test Tax Category 1")
- address = frappe.get_doc(dict(
- doctype='Address',
- address_title='_Test Address With Tax Category',
- tax_category='_Test Tax Category 2',
- address_type='Billing',
- address_line1='Station Road',
- city='_Test City',
- country='India',
- links=[dict(
- link_doctype='Supplier',
- link_name='_Test Supplier With Tax Category'
- )]
- )).insert()
+ address = frappe.get_doc(dict(
+ doctype='Address',
+ address_title='_Test Address With Tax Category',
+ tax_category='_Test Tax Category 2',
+ address_type='Billing',
+ address_line1='Station Road',
+ city='_Test City',
+ country='India',
+ links=[dict(
+ link_doctype='Supplier',
+ link_name='_Test Supplier With Tax Category'
+ )]
+ )).insert()
- # Tax Category with Address
- details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
- self.assertEqual(details.tax_category, "_Test Tax Category 2")
+ # Tax Category with Address
+ details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
+ self.assertEqual(details.tax_category, "_Test Tax Category 2")
- # Rollback
- address.delete()
+ # Rollback
+ address.delete()
def create_supplier(**args):
- args = frappe._dict(args)
+ args = frappe._dict(args)
- try:
- doc = frappe.get_doc({
- "doctype": "Supplier",
- "supplier_name": args.supplier_name,
- "supplier_group": args.supplier_group or "Services",
- "supplier_type": args.supplier_type or "Company",
- "tax_withholding_category": args.tax_withholding_category
- }).insert()
+ if frappe.db.exists("Supplier", args.supplier_name):
+ return frappe.get_doc("Supplier", args.supplier_name)
- return doc
+ doc = frappe.get_doc({
+ "doctype": "Supplier",
+ "supplier_name": args.supplier_name,
+ "supplier_group": args.supplier_group or "Services",
+ "supplier_type": args.supplier_type or "Company",
+ "tax_withholding_category": args.tax_withholding_category
+ }).insert()
- except frappe.DuplicateEntryError:
- return frappe.get_doc("Supplier", args.supplier_name)
+ return doc
diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
index 8519e68d09..6be8c94ad9 100644
--- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
+++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
@@ -175,7 +175,7 @@ class TestShoppingCart(unittest.TestCase):
def create_tax_rule(self):
tax_rule = frappe.get_test_records("Tax Rule")[0]
try:
- frappe.get_doc(tax_rule).insert()
+ frappe.get_doc(tax_rule).insert(ignore_if_duplicate=True)
except (frappe.DuplicateEntryError, ConflictingTaxRule):
pass
diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
index 54ed6f7d11..26bd19f010 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
@@ -82,7 +82,7 @@ class TallyMigration(Document):
"is_private": True
})
try:
- f.insert()
+ f.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
setattr(self, key, f.file_url)
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index a2df26c3e2..6e52eb97ca 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -142,7 +142,7 @@ class Employee(NestedSet):
"file_url": self.image,
"attached_to_doctype": "User",
"attached_to_name": self.user_id
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
# already exists
pass
diff --git a/erpnext/hr/doctype/exit_interview/exit_interview.py b/erpnext/hr/doctype/exit_interview/exit_interview.py
index 30e19f1c9b..59fb2fd9ca 100644
--- a/erpnext/hr/doctype/exit_interview/exit_interview.py
+++ b/erpnext/hr/doctype/exit_interview/exit_interview.py
@@ -128,4 +128,4 @@ def show_email_summary(email_success, email_failure):
message += _('{0} due to missing email information for employee(s): {1}').format(
frappe.bold('Sending Failed'), ', '.join(email_failure))
- frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True)
\ No newline at end of file
+ frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True)
diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
index acd50f278c..abb288723c 100644
--- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
+++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
@@ -82,7 +82,7 @@ def get_vehicle(employee_id):
"vehicle_value": flt(500000)
})
try:
- vehicle.insert()
+ vehicle.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
return license_plate
diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
index b30d983adc..c3be146bec 100644
--- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py
+++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
@@ -21,7 +21,7 @@ class TestHomepageSection(unittest.TestCase):
{'title': 'Card 2', 'subtitle': 'Subtitle 2', 'content': 'This is test card 2', 'image': 'test.jpg'},
],
'no_of_columns': 3
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 074bd527e2..e835690969 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -53,10 +53,7 @@ def create_hsn_codes(data, code_field):
hsn_code.description = d["description"]
hsn_code.hsn_code = d[code_field]
hsn_code.name = d[code_field]
- try:
- hsn_code.db_insert()
- except frappe.DuplicateEntryError:
- pass
+ hsn_code.db_insert(ignore_if_duplicate=True)
def add_custom_roles_for_reports():
for report_name in ('GST Sales Register', 'GST Purchase Register',
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index 4441bb9562..a4f2207f11 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -155,7 +155,7 @@ def insert_record(records):
doc = frappe.new_doc(r.get("doctype"))
doc.update(r)
try:
- doc.insert(ignore_permissions=True)
+ doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
except frappe.DuplicateEntryError as e:
# pass DuplicateEntryError and continue
if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name:
diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py
index baa03024af..613dd3f14d 100644
--- a/erpnext/stock/doctype/batch/test_batch.py
+++ b/erpnext/stock/doctype/batch/test_batch.py
@@ -433,14 +433,13 @@ def create_price_list_for_batch(item_code, batch, rate):
def make_new_batch(**args):
args = frappe._dict(args)
- try:
+ if frappe.db.exists("Batch", args.batch_id):
+ batch = frappe.get_doc("Batch", args.batch_id)
+ else:
batch = frappe.get_doc({
"doctype": "Batch",
"batch_id": args.batch_id,
"item": args.item_code,
}).insert()
- except frappe.DuplicateEntryError:
- batch = frappe.get_doc("Batch", args.batch_id)
-
return batch
From 5ff3705872960190031066dbe34158ad3c659820 Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 23 Feb 2022 14:54:16 +0530
Subject: [PATCH 39/64] test: Make Variant if absent in
`test_variant_work_order`, keep test atomic
---
erpnext/stock/doctype/stock_entry/test_stock_entry.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 7ab41418ae..c5afa49166 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -691,6 +691,8 @@ class TestStockEntry(ERPNextTestCase):
bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item",
"is_default": 1, "docstatus": 1})
+ make_item_variant() # make variant of _Test Variant Item if absent
+
work_order = frappe.new_doc("Work Order")
work_order.update({
"company": "_Test Company",
From b44cead3179cf200e382895cd415d6a6e79d7fca Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Wed, 23 Feb 2022 16:17:41 +0530
Subject: [PATCH 40/64] test: fix flaky stateful tests (#29749)
Co-Authored-By: Marica
---
.../opening_invoice_creation_tool.py | 2 +-
.../test_opening_invoice_creation_tool.py | 39 ++++++++-----------
2 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index ade7f8146b..6e7b80e731 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -166,7 +166,7 @@ class OpeningInvoiceCreationTool(Document):
frappe.scrub(row.party_type): row.party,
"is_pos": 0,
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
- "update_stock": 0,
+ "update_stock": 0, # important: https://github.com/frappe/erpnext/pull/23559
"invoice_number": row.invoice_number,
"disable_rounded_total": 1
})
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
index 6700e9b975..3eaf6a28f3 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
@@ -1,11 +1,7 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
-
import frappe
-from frappe.cache_manager import clear_doctype_cache
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import (
create_dimension,
@@ -14,14 +10,17 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp
from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import (
get_temporary_opening_account,
)
+from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ["Customer", "Supplier", "Accounting Dimension"]
-class TestOpeningInvoiceCreationTool(unittest.TestCase):
- def setUp(self):
+class TestOpeningInvoiceCreationTool(ERPNextTestCase):
+ @classmethod
+ def setUpClass(self):
if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
make_company()
create_dimension()
+ return super().setUpClass()
def make_invoices(self, invoice_type="Sales", company=None, party_1=None, party_2=None, invoice_number=None, department=None):
doc = frappe.get_single("Opening Invoice Creation Tool")
@@ -31,26 +30,20 @@ class TestOpeningInvoiceCreationTool(unittest.TestCase):
return doc.make_invoices()
def test_opening_sales_invoice_creation(self):
- property_setter = make_property_setter("Sales Invoice", "update_stock", "default", 1, "Check")
- try:
- invoices = self.make_invoices(company="_Test Opening Invoice Company")
+ invoices = self.make_invoices(company="_Test Opening Invoice Company")
- self.assertEqual(len(invoices), 2)
- expected_value = {
- "keys": ["customer", "outstanding_amount", "status"],
- 0: ["_Test Customer", 300, "Overdue"],
- 1: ["_Test Customer 1", 250, "Overdue"],
- }
- self.check_expected_values(invoices, expected_value)
+ self.assertEqual(len(invoices), 2)
+ expected_value = {
+ "keys": ["customer", "outstanding_amount", "status"],
+ 0: ["_Test Customer", 300, "Overdue"],
+ 1: ["_Test Customer 1", 250, "Overdue"],
+ }
+ self.check_expected_values(invoices, expected_value)
- si = frappe.get_doc("Sales Invoice", invoices[0])
+ si = frappe.get_doc("Sales Invoice", invoices[0])
- # Check if update stock is not enabled
- self.assertEqual(si.update_stock, 0)
-
- finally:
- property_setter.delete()
- clear_doctype_cache("Sales Invoice")
+ # Check if update stock is not enabled
+ self.assertEqual(si.update_stock, 0)
def check_expected_values(self, invoices, expected_value, invoice_type="Sales"):
doctype = "Sales Invoice" if invoice_type == "Sales" else "Purchase Invoice"
From a33f04ea41087305c95111aa86bf96d3df2e2b36 Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 23 Feb 2022 16:26:20 +0530
Subject: [PATCH 41/64] fix: Check if both old and new items have bundles
before merging
- If only one has bundle against it, they can be merged
---
erpnext/stock/doctype/item/item.py | 8 +++++---
erpnext/stock/doctype/item/test_item.py | 1 +
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d984d6eb99..494fb3b8bb 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -465,9 +465,11 @@ class Item(Document):
def validate_duplicate_product_bundles_before_merge(self, old_name, new_name):
"Block merge if both old and new items have product bundles."
- bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name})
- if bundle:
- bundle_link = get_link_to_form("Product Bundle", bundle)
+ old_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name})
+ new_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": new_name})
+
+ if old_bundle and new_bundle:
+ bundle_link = get_link_to_form("Product Bundle", old_bundle)
old_name, new_name = frappe.bold(old_name), frappe.bold(new_name)
msg = _("Please delete Product Bundle {0}, before merging {1} into {2}").format(
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 6f5f1ff786..9491e17259 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -397,6 +397,7 @@ class TestItem(ERPNextTestCase):
create_item("Test Item inside Bundle")
bundle_items = ["Test Item inside Bundle"]
+ # make bundles for both items
bundle1 = make_product_bundle("Test Item Bundle Item 1", bundle_items, qty=2)
make_product_bundle("Test Item Bundle Item 2", bundle_items, qty=2)
From 239733acd1ad770fc58b5bedd2cf0bb6e75c569d Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 23 Feb 2022 20:41:49 +0530
Subject: [PATCH 42/64] fix: Make abbreviation limit to 10
---
erpnext/public/js/setup_wizard.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js
index e746ce9ae0..83b69aebc5 100644
--- a/erpnext/public/js/setup_wizard.js
+++ b/erpnext/public/js/setup_wizard.js
@@ -78,11 +78,11 @@ erpnext.setup.slides_settings = [
slide.get_input("company_name").on("change", function () {
var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join("");
- slide.get_field("company_abbr").set_value(abbr.slice(0, 5).toUpperCase());
+ slide.get_field("company_abbr").set_value(abbr.slice(0, 10).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
slide.get_input("company_abbr").on("change", function () {
- if (slide.get_input("company_abbr").val().length > 5) {
+ if (slide.get_input("company_abbr").val().length > 10) {
frappe.msgprint(__("Company Abbreviation cannot have more than 5 characters"));
slide.get_field("company_abbr").set_value("");
}
@@ -96,7 +96,7 @@ erpnext.setup.slides_settings = [
if (!this.values.company_abbr) {
return false;
}
- if (this.values.company_abbr.length > 5) {
+ if (this.values.company_abbr.length > 10) {
return false;
}
return true;
From 03739147049ed78bd2bb43f5f47cfc70d6be43ba Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 24 Feb 2022 14:42:56 +0530
Subject: [PATCH 43/64] fix: Commission not applied while making Sales Order
from Quotation
---
.../doctype/sales_invoice_item/sales_invoice_item.json | 6 ++++--
.../doctype/sales_order_item/sales_order_item.json | 7 +++++--
.../doctype/delivery_note_item/delivery_note_item.json | 9 ++++++---
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index ae9ac35729..2901cf0888 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -832,6 +832,7 @@
},
{
"default": "0",
+ "fetch_from": "item_code.grant_commission",
"fieldname": "grant_commission",
"fieldtype": "Check",
"label": "Grant Commission",
@@ -841,7 +842,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-10-05 12:24:54.968907",
+ "modified": "2022-02-24 14:41:36.392560",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
@@ -849,5 +850,6 @@
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index 080d517d13..7e55499533 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -83,8 +83,8 @@
"planned_qty",
"column_break_69",
"work_order_qty",
- "produced_qty",
"delivered_qty",
+ "produced_qty",
"returned_qty",
"shopping_cart_section",
"additional_notes",
@@ -701,8 +701,10 @@
"width": "50px"
},
{
+ "description": "For Production",
"fieldname": "produced_qty",
"fieldtype": "Float",
+ "hidden": 1,
"label": "Produced Quantity",
"oldfieldname": "produced_qty",
"oldfieldtype": "Currency",
@@ -791,6 +793,7 @@
},
{
"default": "0",
+ "fetch_from": "item_code.grant_commission",
"fieldname": "grant_commission",
"fieldtype": "Check",
"label": "Grant Commission",
@@ -800,7 +803,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2022-02-21 13:55:08.883104",
+ "modified": "2022-02-24 14:41:57.325799",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order Item",
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 51c88bed61..f1f5d96e62 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -757,6 +757,7 @@
},
{
"default": "0",
+ "fetch_from": "item_code.grant_commission",
"fieldname": "grant_commission",
"fieldtype": "Check",
"label": "Grant Commission",
@@ -767,12 +768,14 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-10-06 12:12:44.018872",
+ "modified": "2022-02-24 14:42:20.211085",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",
+ "naming_rule": "Random",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
- "sort_order": "DESC"
-}
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
From 761e528ba39d5acdbd0bb7dd8cec48705d80cfc3 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Thu, 24 Feb 2022 17:57:39 +0530
Subject: [PATCH 44/64] fix: deprecation warning
---
erpnext/patches/v13_0/non_profit_deprecation_warning.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/patches/v13_0/non_profit_deprecation_warning.py b/erpnext/patches/v13_0/non_profit_deprecation_warning.py
index c170de5c1c..5b54b25a5b 100644
--- a/erpnext/patches/v13_0/non_profit_deprecation_warning.py
+++ b/erpnext/patches/v13_0/non_profit_deprecation_warning.py
@@ -5,6 +5,6 @@ def execute():
click.secho(
"Non Profit Domain is moved to a separate app and will be removed from ERPNext in version-14.\n"
- "When upgrading to ERPNext version-14, please install the app to continue using the Agriculture domain: https://github.com/frappe/non_profit",
+ "When upgrading to ERPNext version-14, please install the app to continue using the Non Profit domain: https://github.com/frappe/non_profit",
fg="yellow",
)
From 04b9091821fbd64b1417883087f6a25bcab5a101 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Thu, 24 Feb 2022 18:10:29 +0530
Subject: [PATCH 45/64] fix: web form deletion
---
erpnext/patches/v14_0/delete_non_profit_doctypes.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
index d53aecca92..565b10cbb8 100644
--- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -32,7 +32,7 @@ def execute():
forms = ['grant-application', 'certification-application', 'certification-application-usd']
for form in forms:
- frappe.delete_doc("Web Form", form, ignore_missing=True)
+ frappe.delete_doc("Web Form", form, ignore_missing=True, force=True)
custom_records = [
{"doctype": "Party Type", "name": "Member"},
From 69c34cd7ae128dde56cde10c53b479331c33d56f Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Fri, 25 Feb 2022 14:36:29 +0530
Subject: [PATCH 46/64] fix(pos): mode of payment disappears after save
---
erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 5229d87017..9b3b3aa414 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -439,7 +439,6 @@ class POSInvoice(SalesInvoice):
self.paid_amount = 0
def set_account_for_mode_of_payment(self):
- self.payments = [d for d in self.payments if d.amount or d.base_amount or d.default]
for pay in self.payments:
if not pay.account:
pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account")
From 81514516f3c7106a5b211796bb74ddad0a6add20 Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Fri, 25 Feb 2022 15:18:06 +0530
Subject: [PATCH 47/64] fix(pos): coupon code is applied even if ignore pricing
rule is check
---
erpnext/public/js/controllers/transaction.js | 18 +++++++------
.../selling/page/point_of_sale/pos_payment.js | 25 +++++++++++--------
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index ae8c0c8c6d..00373a6513 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -2285,13 +2285,17 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
coupon_code() {
- var me = this;
- frappe.run_serially([
- () => this.frm.doc.ignore_pricing_rule=1,
- () => me.ignore_pricing_rule(),
- () => this.frm.doc.ignore_pricing_rule=0,
- () => me.apply_pricing_rule()
- ]);
+ if (this.frm.doc.coupon_code || this.frm._last_coupon_code) {
+ // reset pricing rules if coupon code is set or is unset
+ const _ignore_pricing_rule = this.frm.doc.ignore_pricing_rule;
+ return frappe.run_serially([
+ () => this.frm.doc.ignore_pricing_rule=1,
+ () => this.frm.trigger('ignore_pricing_rule'),
+ () => this.frm.doc.ignore_pricing_rule=_ignore_pricing_rule,
+ () => this.frm.trigger('apply_pricing_rule'),
+ () => this.frm._last_coupon_code = this.frm.doc.coupon_code
+ ]);
+ }
}
};
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
index 4d75e6ef1b..1e9f6d7d92 100644
--- a/erpnext/selling/page/point_of_sale/pos_payment.js
+++ b/erpnext/selling/page/point_of_sale/pos_payment.js
@@ -170,17 +170,20 @@ erpnext.PointOfSale.Payment = class {
});
frappe.ui.form.on('POS Invoice', 'coupon_code', (frm) => {
- if (!frm.doc.ignore_pricing_rule) {
- if (frm.doc.coupon_code) {
- frappe.run_serially([
- () => frm.doc.ignore_pricing_rule=1,
- () => frm.trigger('ignore_pricing_rule'),
- () => frm.doc.ignore_pricing_rule=0,
- () => frm.trigger('apply_pricing_rule'),
- () => frm.save(),
- () => this.update_totals_section(frm.doc)
- ]);
- }
+ if (!frm.doc.ignore_pricing_rule && frm.doc.coupon_code) {
+ frappe.run_serially([
+ () => frm.doc.ignore_pricing_rule=1,
+ () => frm.trigger('ignore_pricing_rule'),
+ () => frm.doc.ignore_pricing_rule=0,
+ () => frm.trigger('apply_pricing_rule'),
+ () => frm.save(),
+ () => this.update_totals_section(frm.doc)
+ ]);
+ } else if (frm.doc.ignore_pricing_rule && frm.doc.coupon_code) {
+ frappe.show_alert({
+ message: __("Ignore Pricing Rule is enabled. Cannot apply coupon code."),
+ indicator: "orange"
+ });
}
});
From fe2ced7bee1713067912787b3e238269adf451ac Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 25 Feb 2022 16:57:59 +0530
Subject: [PATCH 48/64] fix: Regional print format addition
---
erpnext/regional/india/setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index e835690969..2df52a204b 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -111,7 +111,7 @@ def add_permissions():
def add_print_formats():
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
- frappe.reload_doc("accounts", "print_format", "gst_pos_invoice")
+ frappe.reload_doc("selling", "print_format", "gst_pos_invoice")
frappe.reload_doc("accounts", "print_format", "GST E-Invoice")
frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0)
From 36c76c40350cbc030cc2b27a84c1bfebbcad67c3 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 25 Feb 2022 17:15:57 +0530
Subject: [PATCH 49/64] fix: Failing setup wizard test
---
erpnext/hr/doctype/department/department.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py
index ed0bfcf0d5..ecc025a6e3 100644
--- a/erpnext/hr/doctype/department/department.py
+++ b/erpnext/hr/doctype/department/department.py
@@ -32,7 +32,7 @@ class Department(NestedSet):
return new
def on_update(self):
- if not frappe.local.flags.ignore_update_nsm:
+ if not frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard:
super(Department, self).on_update()
def on_trash(self):
From 3e573e9838ef82a5e1b89c3d1dcbd6ce67c361b9 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 25 Feb 2022 17:18:53 +0530
Subject: [PATCH 50/64] fix: Condition
---
erpnext/hr/doctype/department/department.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py
index ecc025a6e3..71300c40b0 100644
--- a/erpnext/hr/doctype/department/department.py
+++ b/erpnext/hr/doctype/department/department.py
@@ -32,7 +32,7 @@ class Department(NestedSet):
return new
def on_update(self):
- if not frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard:
+ if not (frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard):
super(Department, self).on_update()
def on_trash(self):
From 4f463943990057e8ef43eac07e02dc75b9ff8580 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 25 Feb 2022 21:18:22 +0530
Subject: [PATCH 51/64] fix: Add parent to department
---
erpnext/hr/doctype/department/test_records.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/hr/doctype/department/test_records.json b/erpnext/hr/doctype/department/test_records.json
index 654925ef93..e3421f28b8 100644
--- a/erpnext/hr/doctype/department/test_records.json
+++ b/erpnext/hr/doctype/department/test_records.json
@@ -1,4 +1,4 @@
[
- {"doctype":"Department", "department_name":"_Test Department", "company": "_Test Company"},
- {"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company"}
+ {"doctype":"Department", "department_name":"_Test Department", "company": "_Test Company", "parent_department": "All Departments"},
+ {"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company", "parent_department": "All Departments"}
]
\ No newline at end of file
From 71d33081aaf24db12906ec3069270a9df018fa2b Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Fri, 25 Feb 2022 23:01:32 +0530
Subject: [PATCH 52/64] fix: org chart connectors not rendered when Employee
Naming is set to Full Name (#29997)
---
.../js/hierarchy_chart/hierarchy_chart_desktop.js | 14 ++++++++------
.../js/hierarchy_chart/hierarchy_chart_mobile.js | 9 +++++----
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
index 831626aa91..a585aa614f 100644
--- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
+++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
@@ -304,12 +304,13 @@ erpnext.HierarchyChart = class {
}
get_child_nodes(node_id) {
+ let me = this;
return new Promise(resolve => {
frappe.call({
- method: this.method,
+ method: me.method,
args: {
parent: node_id,
- company: this.company
+ company: me.company
}
}).then(r => resolve(r.message));
});
@@ -350,12 +351,13 @@ erpnext.HierarchyChart = class {
}
get_all_nodes() {
+ let me = this;
return new Promise(resolve => {
frappe.call({
method: 'erpnext.utilities.hierarchy_chart.get_all_nodes',
args: {
- method: this.method,
- company: this.company
+ method: me.method,
+ company: me.company
},
callback: (r) => {
resolve(r.message);
@@ -427,8 +429,8 @@ erpnext.HierarchyChart = class {
add_connector(parent_id, child_id) {
// using pure javascript for better performance
- const parent_node = document.querySelector(`#${parent_id}`);
- const child_node = document.querySelector(`#${child_id}`);
+ const parent_node = document.getElementById(`${parent_id}`);
+ const child_node = document.getElementById(`${child_id}`);
let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js
index 0a8ba78f64..52236e7df9 100644
--- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js
+++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js
@@ -235,7 +235,7 @@ erpnext.HierarchyChartMobile = class {
let me = this;
return new Promise(resolve => {
frappe.call({
- method: this.method,
+ method: me.method,
args: {
parent: node_id,
company: me.company,
@@ -286,8 +286,8 @@ erpnext.HierarchyChartMobile = class {
}
add_connector(parent_id, child_id) {
- const parent_node = document.querySelector(`#${parent_id}`);
- const child_node = document.querySelector(`#${child_id}`);
+ const parent_node = document.getElementById(`${parent_id}`);
+ const child_node = document.getElementById(`${child_id}`);
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
@@ -518,7 +518,8 @@ erpnext.HierarchyChartMobile = class {
level.nextAll('li').remove();
let node_object = this.nodes[node.id];
- let current_node = level.find(`#${node.id}`).detach();
+ let current_node = level.find(`[id="${node.id}"]`).detach();
+
current_node.removeClass('active-child active-path');
node_object.expanded = 0;
From 1e7df5d0c2b4a95787adce9a69cfb082c9ad084e Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Sat, 26 Feb 2022 11:07:44 +0530
Subject: [PATCH 53/64] fix(minor): student attendance tool query fix
---
.../student_attendance_tool.js | 28 +++++++++++++------
.../student_attendance_tool.py | 18 ++++++------
.../public/js/education/student_button.html | 17 -----------
erpnext/public/js/erpnext.bundle.js | 1 -
4 files changed, 28 insertions(+), 36 deletions(-)
delete mode 100644 erpnext/public/js/education/student_button.html
diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
index 68e7780039..d8a0304941 100644
--- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
+++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
@@ -163,16 +163,26 @@ education.StudentsEditor = class StudentsEditor {
);
});
- var htmls = students.map(function(student) {
- return frappe.render_template("student_button", {
- student: student.student,
- student_name: student.student_name,
- group_roll_number: student.group_roll_number,
- status: student.status
- })
- });
+ // make html grid of students
+ let student_html = '';
+ for (let student of students) {
+ student_html += `
+
+
+
+ ${student.group_roll_number} - ${student.student_name}
+
+
+
`;
+ }
- $(htmls.join("")).appendTo(me.wrapper);
+ $(student_html).appendTo(me.wrapper);
}
show_empty_state() {
diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
index 7deb6b18da..92bb20ca52 100644
--- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
+++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
@@ -24,24 +24,24 @@ def get_student_attendance_records(based_on, date=None, student_group=None, cour
student_list = frappe.get_all("Student Group Student", fields=["student", "student_name", "group_roll_number"],
filters={"parent": student_group, "active": 1}, order_by= "group_roll_number")
- table = frappe.qb.DocType("Student Attendance")
+ StudentAttendance = frappe.qb.DocType("Student Attendance")
if course_schedule:
student_attendance_list = (
- frappe.qb.from_(table)
- .select(table.student, table.status)
+ frappe.qb.from_(StudentAttendance)
+ .select(StudentAttendance.student, StudentAttendance.status)
.where(
- (table.course_schedule == course_schedule)
+ (StudentAttendance.course_schedule == course_schedule)
)
).run(as_dict=True)
else:
student_attendance_list = (
- frappe.qb.from_(table)
- .select(table.student, table.status)
+ frappe.qb.from_(StudentAttendance)
+ .select(StudentAttendance.student, StudentAttendance.status)
.where(
- (table.student_group == student_group)
- & (table.date == date)
- & (table.course_schedule == "") | (table.course_schedule.isnull())
+ (StudentAttendance.student_group == student_group)
+ & (StudentAttendance.date == date)
+ & ((StudentAttendance.course_schedule == "") | (StudentAttendance.course_schedule.isnull()))
)
).run(as_dict=True)
diff --git a/erpnext/public/js/education/student_button.html b/erpnext/public/js/education/student_button.html
deleted file mode 100644
index b64c73a43c..0000000000
--- a/erpnext/public/js/education/student_button.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- {{ group_roll_number }} - {{ student_name }}
-
-
-
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js
index b3a68b3862..8409e78860 100644
--- a/erpnext/public/js/erpnext.bundle.js
+++ b/erpnext/public/js/erpnext.bundle.js
@@ -16,7 +16,6 @@ import "./templates/item_quick_entry.html";
import "./utils/item_quick_entry";
import "./utils/customer_quick_entry";
import "./utils/supplier_quick_entry";
-import "./education/student_button.html";
import "./education/assessment_result_tool.html";
import "./call_popup/call_popup";
import "./utils/dimension_tree_filter";
From 77ffcd3aed9b6fb99bc6f508897d3ebe6880de15 Mon Sep 17 00:00:00 2001
From: Sagar Sharma
Date: Sat, 26 Feb 2022 11:25:02 +0530
Subject: [PATCH 54/64] fix(ux): make "allow zero valuation rate" readonly if
"s_warehouse" is set (#29681)
* chore: make allow zero valuation rate readonly if s_warehouse is set
* fix: setting the checkbox to zero whenever the source warehouse is set
* fix: remove allow_on_submit and refresh trigger
Co-authored-by: Ankush Menat
---
erpnext/stock/doctype/stock_entry/stock_entry.js | 6 ++++++
.../stock_entry_detail/stock_entry_detail.json | 12 +++++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 5c9da3a205..324ca7ac59 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -629,6 +629,12 @@ frappe.ui.form.on('Stock Entry Detail', {
frm.events.set_serial_no(frm, cdt, cdn, () => {
frm.events.get_warehouse_details(frm, cdt, cdn);
});
+
+ // set allow_zero_valuation_rate to 0 if s_warehouse is selected.
+ let item = frappe.get_doc(cdt, cdn);
+ if (item.s_warehouse) {
+ item.allow_zero_valuation_rate = 0;
+ }
},
t_warehouse: function(frm, cdt, cdn) {
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index df65706c39..83aed904dd 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -1,7 +1,7 @@
{
"actions": [],
"autoname": "hash",
- "creation": "2013-03-29 18:22:12",
+ "creation": "2022-02-05 00:17:49.860824",
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
@@ -340,13 +340,13 @@
"label": "More Information"
},
{
- "allow_on_submit": 1,
"default": "0",
"fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check",
"label": "Allow Zero Valuation Rate",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "read_only_depends_on": "eval:doc.s_warehouse"
},
{
"allow_on_submit": 1,
@@ -556,12 +556,14 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-06-22 16:47:11.268975",
+ "modified": "2022-02-26 00:51:24.963653",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
+ "naming_rule": "Random",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
- "sort_order": "ASC"
+ "sort_order": "ASC",
+ "states": []
}
\ No newline at end of file
From 2dabda03af4407d39c58c0074656048a0860ce8d Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Sat, 26 Feb 2022 11:32:54 +0530
Subject: [PATCH 55/64] fix(minor): student_attendance_tool.js fix fetching UX
---
.../student_attendance_tool.js | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
index d8a0304941..4526585175 100644
--- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
+++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
@@ -3,6 +3,10 @@
frappe.provide("education");
frappe.ui.form.on('Student Attendance Tool', {
+ setup: (frm) => {
+ frm.students_area = $('')
+ .appendTo(frm.fields_dict.students_html.wrapper);
+ },
onload: function(frm) {
frm.set_query("student_group", function() {
return {
@@ -34,6 +38,7 @@ frappe.ui.form.on('Student Attendance Tool', {
student_group: function(frm) {
if ((frm.doc.student_group && frm.doc.date) || frm.doc.course_schedule) {
+ frm.students_area.find('.student-attendance-checks').html(`
Fetching...
`);
var method = "erpnext.education.doctype.student_attendance_tool.student_attendance_tool.get_student_attendance_records";
frappe.call({
@@ -62,10 +67,6 @@ frappe.ui.form.on('Student Attendance Tool', {
},
get_students: function(frm, students) {
- if (!frm.students_area) {
- frm.students_area = $('
')
- .appendTo(frm.fields_dict.students_html.wrapper);
- }
students = students || [];
frm.students_editor = new education.StudentsEditor(frm, frm.students_area, students);
}
@@ -182,7 +183,7 @@ education.StudentsEditor = class StudentsEditor {
`;
}
- $(student_html).appendTo(me.wrapper);
+ $(`
${student_html}
`).appendTo(me.wrapper);
}
show_empty_state() {
From 96e87fe3c9bb339b6e8046834b1fab6493113096 Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Sat, 26 Feb 2022 12:54:13 +0530
Subject: [PATCH 56/64] fix: validate Work Order qty against Production Plan
(#29721) (#30003)
* fix: validate Work Order qty against Production Plan
* chore: err msg when max_qty is 0
* test: add test for overproduction
* fix: CI
(cherry picked from commit 067ede76ea0851a29e270e150f482368e0afa194)
Co-authored-by: Sagar Sharma
---
.../production_plan/test_production_plan.py | 20 +++++++++++--------
.../doctype/work_order/work_order.py | 15 ++++++++++++++
2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index d88e10a564..2359815813 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -9,6 +9,7 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import (
get_sales_orders,
get_warehouse_list,
)
+from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@@ -466,26 +467,29 @@ class TestProductionPlan(ERPNextTestCase):
bom = make_bom(item=item, raw_materials=raw_materials)
# Create Production Plan
- pln = create_production_plan(item_code=bom.item, planned_qty=10)
+ pln = create_production_plan(item_code=bom.item, planned_qty=5)
# All the created Work Orders
wo_list = []
- # Create and Submit 1st Work Order for 5 qty
- create_work_order(item, pln, 5)
+ # Create and Submit 1st Work Order for 3 qty
+ create_work_order(item, pln, 3)
+ pln.reload()
+ self.assertEqual(pln.po_items[0].ordered_qty, 3)
+
+ # Create and Submit 2nd Work Order for 2 qty
+ create_work_order(item, pln, 2)
pln.reload()
self.assertEqual(pln.po_items[0].ordered_qty, 5)
- # Create and Submit 2nd Work Order for 3 qty
- create_work_order(item, pln, 3)
- pln.reload()
- self.assertEqual(pln.po_items[0].ordered_qty, 8)
+ # Overproduction
+ self.assertRaises(OverProductionError, create_work_order, item=item, pln=pln, qty=2)
# Cancel 1st Work Order
wo1 = frappe.get_doc("Work Order", wo_list[0])
wo1.cancel()
pln.reload()
- self.assertEqual(pln.po_items[0].ordered_qty, 3)
+ self.assertEqual(pln.po_items[0].ordered_qty, 2)
# Cancel 2nd Work Order
wo2 = frappe.get_doc("Work Order", wo_list[1])
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index ed6a0299ef..e1120c723d 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -636,6 +636,21 @@ class WorkOrder(Document):
if not self.qty > 0:
frappe.throw(_("Quantity to Manufacture must be greater than 0."))
+ if self.production_plan and self.production_plan_item:
+ qty_dict = frappe.db.get_value("Production Plan Item", self.production_plan_item, ["planned_qty", "ordered_qty"], as_dict=1)
+
+ allowance_qty =flt(frappe.db.get_single_value("Manufacturing Settings",
+ "overproduction_percentage_for_work_order"))/100 * qty_dict.get("planned_qty", 0)
+
+ max_qty = qty_dict.get("planned_qty", 0) + allowance_qty - qty_dict.get("ordered_qty", 0)
+
+ if max_qty < 1:
+ frappe.throw(_("Cannot produce more item for {0}")
+ .format(self.production_item), OverProductionError)
+ elif self.qty > max_qty:
+ frappe.throw(_("Cannot produce more than {0} items for {1}")
+ .format(max_qty, self.production_item), OverProductionError)
+
def validate_transfer_against(self):
if not self.docstatus == 1:
# let user configure operations until they're ready to submit
From 4e9a9f35a605f4f886cc9cc920ec4ab4262b9709 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 28 Feb 2022 12:41:59 +0530
Subject: [PATCH 57/64] test: add correct test case
---
.../doctype/sales_invoice/test_sales_invoice.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 941061f2a2..07591e7b1e 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -2429,14 +2429,22 @@ class TestSalesInvoice(unittest.TestCase):
def test_sales_commission(self):
- si = frappe.copy_doc(test_records[0])
+ si = frappe.copy_doc(test_records[2])
+
+ frappe.db.set_value('Item', si.get('items')[0].item_code, 'grant_commission', 1)
+ frappe.db.set_value('Item', si.get('items')[1].item_code, 'grant_commission', 0)
+
item = copy.deepcopy(si.get('items')[0])
item.update({
"qty": 1,
"rate": 500,
- "grant_commission": 1
})
- si.append("items", item)
+
+ item = copy.deepcopy(si.get('items')[1])
+ item.update({
+ "qty": 1,
+ "rate": 500,
+ })
# Test valid values
for commission_rate, total_commission in ((0, 0), (10, 50), (100, 500)):
From 88a21ca7d2fd2944912bc3cd48c81185478f3cb3 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Wed, 26 Jan 2022 01:01:10 +0530
Subject: [PATCH 58/64] fix: only show child warehouses for transfer
---
erpnext/stock/dashboard/item_dashboard.js | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 37e9e89a0a..204d62355c 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -213,7 +213,14 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call
label: __('Target Warehouse'),
fieldtype: 'Link',
options: 'Warehouse',
- reqd: 1
+ reqd: 1,
+ get_query() {
+ return {
+ filters: {
+ is_group: 0
+ }
+ }
+ }
},
{
fieldname: 'qty',
From 0bed5927779c823455e9cd819cba5281d297e1b3 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Wed, 26 Jan 2022 01:01:33 +0530
Subject: [PATCH 59/64] fix: open stock entry instead of submitting from item
dashboard
---
erpnext/stock/dashboard/item_dashboard.js | 61 ++++++-----------------
1 file changed, 15 insertions(+), 46 deletions(-)
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 204d62355c..1f259bd425 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -259,52 +259,21 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call
dialog.get_field('target').refresh();
}
- dialog.set_primary_action(__('Submit'), function () {
- var values = dialog.get_values();
- if (!values) {
- return;
- }
- if (source && values.qty > actual_qty) {
- frappe.msgprint(__('Quantity must be less than or equal to {0}', [actual_qty]));
- return;
- }
- if (values.source === values.target) {
- frappe.msgprint(__('Source and target warehouse must be different'));
- }
-
- frappe.call({
- method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
- args: values,
- btn: dialog.get_primary_btn(),
- freeze: true,
- freeze_message: __('Creating Stock Entry'),
- callback: function (r) {
- frappe.show_alert(__('Stock Entry {0} created',
- ['' + r.message.name + ' ']));
- dialog.hide();
- callback(r);
- },
+ dialog.set_primary_action(__('Create Stock Entry'), function () {
+ frappe.model.with_doctype('Stock Entry', function () {
+ let doc = frappe.model.get_new_doc('Stock Entry');
+ doc.from_warehouse = dialog.get_value('source');
+ doc.to_warehouse = dialog.get_value('target');
+ doc.stock_entry_type = doc.from_warehouse ? "Material Transfer" : "Material Receipt";
+ let row = frappe.model.add_child(doc, 'items');
+ row.item_code = dialog.get_value('item_code');
+ row.f_warehouse = dialog.get_value('target');
+ row.t_warehouse = dialog.get_value('target');
+ row.qty = dialog.get_value('qty');
+ row.conversion_factor = 1;
+ row.transfer_qty = dialog.get_value('qty');
+ row.basic_rate = dialog.get_value('rate');
+ frappe.set_route('Form', doc.doctype, doc.name);
});
});
-
- $('' +
- __("Add more items or open full form") + '
')
- .appendTo(dialog.body)
- .find('.link-open')
- .on('click', function () {
- frappe.model.with_doctype('Stock Entry', function () {
- var doc = frappe.model.get_new_doc('Stock Entry');
- doc.from_warehouse = dialog.get_value('source');
- doc.to_warehouse = dialog.get_value('target');
- var row = frappe.model.add_child(doc, 'items');
- row.item_code = dialog.get_value('item_code');
- row.f_warehouse = dialog.get_value('target');
- row.t_warehouse = dialog.get_value('target');
- row.qty = dialog.get_value('qty');
- row.conversion_factor = 1;
- row.transfer_qty = dialog.get_value('qty');
- row.basic_rate = dialog.get_value('rate');
- frappe.set_route('Form', doc.doctype, doc.name);
- });
- });
};
From 3cc47d5ba5b0b7a0a677e81bf4d092f85b36e969 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Mon, 28 Feb 2022 13:04:24 +0530
Subject: [PATCH 60/64] fix: correct fieldname for source warehouse
---
erpnext/stock/dashboard/item_dashboard.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 1f259bd425..c9d5f61f22 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -267,7 +267,7 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call
doc.stock_entry_type = doc.from_warehouse ? "Material Transfer" : "Material Receipt";
let row = frappe.model.add_child(doc, 'items');
row.item_code = dialog.get_value('item_code');
- row.f_warehouse = dialog.get_value('target');
+ row.s_warehouse = dialog.get_value('source');
row.t_warehouse = dialog.get_value('target');
row.qty = dialog.get_value('qty');
row.conversion_factor = 1;
From 1d1203d5eca07e40d8ce32248a0d81b0d7130627 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Mon, 28 Feb 2022 12:44:39 +0530
Subject: [PATCH 61/64] fix: dont fetch draft/cancelled BOMs
---
.../manufacturing/doctype/production_plan/production_plan.js | 2 +-
erpnext/manufacturing/doctype/work_order/work_order.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js
index 0babf875e7..c33e64674e 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.js
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js
@@ -49,7 +49,7 @@ frappe.ui.form.on('Production Plan', {
if (d.item_code) {
return {
query: "erpnext.controllers.queries.bom",
- filters:{'item': cstr(d.item_code)}
+ filters:{'item': cstr(d.item_code), 'docstatus': 1}
}
} else frappe.msgprint(__("Please enter Item first"));
}
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index e1120c723d..374ab86cad 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -854,7 +854,7 @@ def get_item_details(item, project = None, skip_bom_info=False):
res = res[0]
if skip_bom_info: return res
- filters = {"item": item, "is_default": 1}
+ filters = {"item": item, "is_default": 1, "docstatus": 1}
if project:
filters = {"item": item, "project": project}
From 39d3f20d9b45939e1b7a5564a1c79ad99a304953 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 28 Feb 2022 14:19:48 +0530
Subject: [PATCH 62/64] fix: removed validation to check zero qty
---
erpnext/controllers/subcontracting.py | 8 --------
1 file changed, 8 deletions(-)
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index 3addb91aaa..c52c688b73 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -363,8 +363,6 @@ class Subcontracting():
return
for row in self.get(self.raw_material_table):
- self.__validate_consumed_qty(row)
-
key = (row.rm_item_code, row.main_item_code, row.purchase_order)
if not self.__transferred_items or not self.__transferred_items.get(key):
return
@@ -372,12 +370,6 @@ class Subcontracting():
self.__validate_batch_no(row, key)
self.__validate_serial_no(row, key)
- def __validate_consumed_qty(self, row):
- if self.backflush_based_on != 'BOM' and flt(row.consumed_qty) == 0.0:
- msg = f'Row {row.idx}: the consumed qty cannot be zero for the item {frappe.bold(row.rm_item_code)}'
-
- frappe.throw(_(msg),title=_('Consumed Items Qty Check'))
-
def __validate_batch_no(self, row, key):
if row.get('batch_no') and row.get('batch_no') not in self.__transferred_items.get(key).get('batch_no'):
link = get_link_to_form('Purchase Order', row.purchase_order)
From b0d1e6db54ea73af5a2b31d32cd5ba360d0dd7b1 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Mon, 28 Feb 2022 16:55:46 +0530
Subject: [PATCH 63/64] test(refactor): use FrappeTestCase
---
.../test_opening_invoice_creation_tool.py | 4 +-
.../shopping_cart/test_shopping_cart.py | 3 +-
.../variant_selector/test_variant_selector.py | 6 +-
.../blanket_order/test_blanket_order.py | 4 +-
erpnext/manufacturing/doctype/bom/test_bom.py | 4 +-
.../bom_update_tool/test_bom_update_tool.py | 4 +-
.../doctype/job_card/test_job_card.py | 4 +-
.../production_plan/test_production_plan.py | 4 +-
.../doctype/routing/test_routing.py | 4 +-
.../doctype/work_order/test_work_order.py | 4 +-
.../doctype/workstation/test_workstation.py | 4 +-
.../selling/doctype/customer/test_customer.py | 5 +-
.../test_party_specific_item.py | 6 +-
.../doctype/quotation/test_quotation.py | 5 +-
.../doctype/sales_order/test_sales_order.py | 4 +-
...st_payment_terms_status_for_sales_order.py | 4 +-
...t_pending_so_items_for_purchase_request.py | 4 +-
.../report/sales_analytics/test_analytics.py | 4 +-
erpnext/stock/doctype/batch/test_batch.py | 4 +-
erpnext/stock/doctype/bin/test_bin.py | 4 +-
.../delivery_note/test_delivery_note.py | 4 +-
.../delivery_trip/test_delivery_trip.py | 5 +-
erpnext/stock/doctype/item/test_item.py | 4 +-
.../item_alternative/test_item_alternative.py | 4 +-
.../item_attribute/test_item_attribute.py | 5 +-
.../doctype/item_price/test_item_price.py | 4 +-
.../test_landed_cost_voucher.py | 4 +-
.../material_request/test_material_request.py | 4 +-
.../doctype/packed_item/test_packed_item.py | 4 +-
.../doctype/packing_slip/test_packing_slip.py | 2 +-
.../stock/doctype/pick_list/test_pick_list.py | 5 +-
.../purchase_receipt/test_purchase_receipt.py | 4 +-
.../doctype/putaway_rule/test_putaway_rule.py | 4 +-
.../test_quality_inspection.py | 4 +-
.../stock/doctype/serial_no/test_serial_no.py | 5 +-
.../stock/doctype/shipment/test_shipment.py | 4 +-
.../doctype/stock_entry/test_stock_entry.py | 4 +-
.../test_stock_ledger_entry.py | 4 +-
.../test_stock_reconciliation.py | 4 +-
.../stock_settings/test_stock_settings.py | 5 +-
.../stock/doctype/warehouse/test_warehouse.py | 4 +-
.../report/stock_ageing/test_stock_ageing.py | 6 +-
.../stock_analytics/test_stock_analytics.py | 5 +-
erpnext/stock/tests/test_valuation.py | 4 +-
erpnext/tests/utils.py | 78 -------------------
45 files changed, 94 insertions(+), 171 deletions(-)
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
index 3eaf6a28f3..77d54a605e 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
@@ -2,6 +2,7 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import (
create_dimension,
@@ -10,11 +11,10 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp
from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import (
get_temporary_opening_account,
)
-from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ["Customer", "Supplier", "Accounting Dimension"]
-class TestOpeningInvoiceCreationTool(ERPNextTestCase):
+class TestOpeningInvoiceCreationTool(FrappeTestCase):
@classmethod
def setUpClass(self):
if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
index 37b3672806..9c389d0d0b 100644
--- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
+++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
@@ -5,6 +5,7 @@
import unittest
import frappe
+from frappe.tests.utils import change_settings
from frappe.utils import add_months, nowdate
from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule
@@ -15,7 +16,7 @@ from erpnext.e_commerce.shopping_cart.cart import (
get_party,
update_cart,
)
-from erpnext.tests.utils import change_settings, create_test_contact_and_address
+from erpnext.tests.utils import create_test_contact_and_address
# test_dependencies = ['Payment Terms Template']
diff --git a/erpnext/e_commerce/variant_selector/test_variant_selector.py b/erpnext/e_commerce/variant_selector/test_variant_selector.py
index 4d907c6221..ee098e16e7 100644
--- a/erpnext/e_commerce/variant_selector/test_variant_selector.py
+++ b/erpnext/e_commerce/variant_selector/test_variant_selector.py
@@ -1,4 +1,5 @@
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.controllers.item_variant import create_variant
from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import (
@@ -7,11 +8,10 @@ from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings imp
from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
from erpnext.e_commerce.variant_selector.utils import get_next_attribute_and_values
from erpnext.stock.doctype.item.test_item import make_item
-from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ["Item"]
-class TestVariantSelector(ERPNextTestCase):
+class TestVariantSelector(FrappeTestCase):
@classmethod
def setUpClass(cls):
@@ -116,4 +116,4 @@ class TestVariantSelector(ERPNextTestCase):
self.assertEqual(next_values["exact_match"][0],"Test-Tshirt-Temp-S-R")
self.assertEqual(next_values["exact_match"][0],"Test-Tshirt-Temp-S-R")
self.assertEqual(price_info["price_list_rate"], 100.0)
- self.assertEqual(price_info["formatted_price_sales_uom"], "₹ 100.00")
\ No newline at end of file
+ self.assertEqual(price_info["formatted_price_sales_uom"], "₹ 100.00")
diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
index eff2344e85..d4d337d841 100644
--- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
+++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
@@ -1,15 +1,15 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_months, today
from erpnext import get_company_currency
-from erpnext.tests.utils import ERPNextTestCase
from .blanket_order import make_order
-class TestBlanketOrder(ERPNextTestCase):
+class TestBlanketOrder(FrappeTestCase):
def setUp(self):
frappe.flags.args = frappe._dict()
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 53437c8012..3cc91b341c 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -7,6 +7,7 @@ from functools import partial
import frappe
from frappe.test_runner import make_test_records
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import cstr, flt
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
@@ -17,11 +18,10 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
create_stock_reconciliation,
)
from erpnext.tests.test_subcontracting import set_backflush_based_on
-from erpnext.tests.utils import ERPNextTestCase
test_records = frappe.get_test_records('BOM')
-class TestBOM(ERPNextTestCase):
+class TestBOM(FrappeTestCase):
def setUp(self):
if not frappe.get_value('Item', '_Test Item'):
make_test_records('Item')
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
index 12576cbf32..b4c625d610 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
@@ -2,15 +2,15 @@
# License: GNU General Public License v3. See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.stock.doctype.item.test_item import create_item
-from erpnext.tests.utils import ERPNextTestCase
test_records = frappe.get_test_records('BOM')
-class TestBOMUpdateTool(ERPNextTestCase):
+class TestBOMUpdateTool(FrappeTestCase):
def test_replace_bom(self):
current_bom = "BOM-_Test Item Home Desktop Manufactured-001"
diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py
index bb5004ba86..33425d2314 100644
--- a/erpnext/manufacturing/doctype/job_card/test_job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py
@@ -2,6 +2,7 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import random_string
from erpnext.manufacturing.doctype.job_card.job_card import OperationMismatchError, OverlapError
@@ -11,10 +12,9 @@ from erpnext.manufacturing.doctype.job_card.job_card import (
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-from erpnext.tests.utils import ERPNextTestCase
-class TestJobCard(ERPNextTestCase):
+class TestJobCard(FrappeTestCase):
def setUp(self):
make_bom_for_jc_tests()
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 2359815813..b2a41ff5b2 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -1,6 +1,7 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_to_date, flt, now_datetime, nowdate
from erpnext.controllers.item_variant import create_variant
@@ -16,10 +17,9 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
create_stock_reconciliation,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestProductionPlan(ERPNextTestCase):
+class TestProductionPlan(FrappeTestCase):
def setUp(self):
for item in ['Test Production Item 1', 'Subassembly Item 1',
'Raw Material Item 1', 'Raw Material Item 2']:
diff --git a/erpnext/manufacturing/doctype/routing/test_routing.py b/erpnext/manufacturing/doctype/routing/test_routing.py
index 8bd60ea4ac..696d9bca14 100644
--- a/erpnext/manufacturing/doctype/routing/test_routing.py
+++ b/erpnext/manufacturing/doctype/routing/test_routing.py
@@ -2,14 +2,14 @@
# See license.txt
import frappe
from frappe.test_runner import make_test_records
+from frappe.tests.utils import FrappeTestCase
from erpnext.manufacturing.doctype.job_card.job_card import OperationSequenceError
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
from erpnext.stock.doctype.item.test_item import make_item
-from erpnext.tests.utils import ERPNextTestCase
-class TestRouting(ERPNextTestCase):
+class TestRouting(FrappeTestCase):
@classmethod
def setUpClass(cls):
cls.item_code = "Test Routing Item - A"
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 67c47efb5b..549ec7b4a6 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -2,6 +2,7 @@
# License: GNU General Public License v3. See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase, timeout
from frappe.utils import add_days, add_months, cint, flt, now, today
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
@@ -21,10 +22,9 @@ from erpnext.stock.doctype.item.test_item import create_item, make_item
from erpnext.stock.doctype.stock_entry import test_stock_entry
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.utils import get_bin
-from erpnext.tests.utils import ERPNextTestCase, timeout
-class TestWorkOrder(ERPNextTestCase):
+class TestWorkOrder(FrappeTestCase):
def setUp(self):
self.warehouse = '_Test Warehouse 2 - _TC'
self.item = '_Test Item'
diff --git a/erpnext/manufacturing/doctype/workstation/test_workstation.py b/erpnext/manufacturing/doctype/workstation/test_workstation.py
index c298c0a8db..dd51017bb7 100644
--- a/erpnext/manufacturing/doctype/workstation/test_workstation.py
+++ b/erpnext/manufacturing/doctype/workstation/test_workstation.py
@@ -2,6 +2,7 @@
# See license.txt
import frappe
from frappe.test_runner import make_test_records
+from frappe.tests.utils import FrappeTestCase
from erpnext.manufacturing.doctype.operation.test_operation import make_operation
from erpnext.manufacturing.doctype.routing.test_routing import create_routing, setup_bom
@@ -10,13 +11,12 @@ from erpnext.manufacturing.doctype.workstation.workstation import (
WorkstationHolidayError,
check_if_within_operating_hours,
)
-from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ["Warehouse"]
test_records = frappe.get_test_records('Workstation')
make_test_records('Workstation')
-class TestWorkstation(ERPNextTestCase):
+class TestWorkstation(FrappeTestCase):
def test_validate_timings(self):
check_if_within_operating_hours("_Test Workstation 1", "Operation 1", "2013-02-02 11:00:00", "2013-02-02 19:00:00")
check_if_within_operating_hours("_Test Workstation 1", "Operation 1", "2013-02-02 10:00:00", "2013-02-02 20:00:00")
diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py
index 5301fd0524..165ee81872 100644
--- a/erpnext/selling/doctype/customer/test_customer.py
+++ b/erpnext/selling/doctype/customer/test_customer.py
@@ -4,12 +4,13 @@
import frappe
from frappe.test_runner import make_test_records
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt
from erpnext.accounts.party import get_due_date
from erpnext.exceptions import PartyDisabled, PartyFrozen
from erpnext.selling.doctype.customer.customer import get_credit_limit, get_customer_outstanding
-from erpnext.tests.utils import ERPNextTestCase, create_test_contact_and_address
+from erpnext.tests.utils import create_test_contact_and_address
test_ignore = ["Price List"]
test_dependencies = ['Payment Term', 'Payment Terms Template']
@@ -17,7 +18,7 @@ test_records = frappe.get_test_records('Customer')
-class TestCustomer(ERPNextTestCase):
+class TestCustomer(FrappeTestCase):
def setUp(self):
if not frappe.get_value('Item', '_Test Item'):
make_test_records('Item')
diff --git a/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py b/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py
index b951044f33..9b672b4b5d 100644
--- a/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py
+++ b/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py
@@ -1,12 +1,10 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
-
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.controllers.queries import item_query
-from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ['Item', 'Customer', 'Supplier']
@@ -18,7 +16,7 @@ def create_party_specific_item(**args):
psi.based_on_value = args.get('based_on_value')
psi.insert()
-class TestPartySpecificItem(ERPNextTestCase):
+class TestPartySpecificItem(FrappeTestCase):
def setUp(self):
self.customer = frappe.get_last_doc("Customer")
self.supplier = frappe.get_last_doc("Supplier")
diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py
index 4357201d23..a749d9e1f1 100644
--- a/erpnext/selling/doctype/quotation/test_quotation.py
+++ b/erpnext/selling/doctype/quotation/test_quotation.py
@@ -2,14 +2,13 @@
# License: GNU General Public License v3. See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, add_months, flt, getdate, nowdate
-from erpnext.tests.utils import ERPNextTestCase
-
test_dependencies = ["Product Bundle"]
-class TestQuotation(ERPNextTestCase):
+class TestQuotation(FrappeTestCase):
def test_make_quotation_without_terms(self):
quotation = make_quotation(do_not_save=1)
self.assertFalse(quotation.get('payment_schedule'))
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 73c5bd299a..f5a34c0eec 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -6,6 +6,7 @@ import json
import frappe
import frappe.permissions
from frappe.core.doctype.user_permission.test_user_permission import create_user
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, flt, getdate, nowdate, today
from erpnext.controllers.accounts_controller import update_child_qty_rate
@@ -27,10 +28,9 @@ from erpnext.selling.doctype.sales_order.sales_order import (
)
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-from erpnext.tests.utils import ERPNextTestCase
-class TestSalesOrder(ERPNextTestCase):
+class TestSalesOrder(FrappeTestCase):
@classmethod
def setUpClass(cls):
diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py
index cad41e1dc0..f7f8a5dbce 100644
--- a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py
+++ b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py
@@ -1,6 +1,7 @@
import datetime
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days
from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
@@ -9,12 +10,11 @@ from erpnext.selling.report.payment_terms_status_for_sales_order.payment_terms_s
execute,
)
from erpnext.stock.doctype.item.test_item import create_item
-from erpnext.tests.utils import ERPNextTestCase
test_dependencies = ["Sales Order", "Item", "Sales Invoice", "Payment Terms Template"]
-class TestPaymentTermsStatusForSalesOrder(ERPNextTestCase):
+class TestPaymentTermsStatusForSalesOrder(FrappeTestCase):
def create_payment_terms_template(self):
# create template for 50-50 payments
template = None
diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py
index d62915fc66..16162acc8f 100644
--- a/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py
+++ b/erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py
@@ -2,6 +2,7 @@
# For license information, please see license.txt
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_months, nowdate
from erpnext.selling.doctype.sales_order.sales_order import make_material_request
@@ -9,10 +10,9 @@ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_orde
from erpnext.selling.report.pending_so_items_for_purchase_request.pending_so_items_for_purchase_request import (
execute,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestPendingSOItemsForPurchaseRequest(ERPNextTestCase):
+class TestPendingSOItemsForPurchaseRequest(FrappeTestCase):
def test_result_for_partial_material_request(self):
so = make_sales_order()
mr=make_material_request(so.name)
diff --git a/erpnext/selling/report/sales_analytics/test_analytics.py b/erpnext/selling/report/sales_analytics/test_analytics.py
index f56cce2dfd..564f48fef3 100644
--- a/erpnext/selling/report/sales_analytics/test_analytics.py
+++ b/erpnext/selling/report/sales_analytics/test_analytics.py
@@ -3,13 +3,13 @@
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.selling.report.sales_analytics.sales_analytics import execute
-from erpnext.tests.utils import ERPNextTestCase
-class TestAnalytics(ERPNextTestCase):
+class TestAnalytics(FrappeTestCase):
def test_sales_analytics(self):
frappe.db.sql("delete from `tabSales Order` where company='_Test Company 2'")
diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py
index 613dd3f14d..5763753853 100644
--- a/erpnext/stock/doctype/batch/test_batch.py
+++ b/erpnext/stock/doctype/batch/test_batch.py
@@ -5,6 +5,7 @@ import json
import frappe
from frappe.exceptions import ValidationError
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import cint, flt
from frappe.utils.data import add_to_date, getdate
@@ -16,10 +17,9 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
)
from erpnext.stock.get_item_details import get_item_details
from erpnext.stock.stock_ledger import get_valuation_rate
-from erpnext.tests.utils import ERPNextTestCase
-class TestBatch(ERPNextTestCase):
+class TestBatch(FrappeTestCase):
def test_item_has_batch_enabled(self):
self.assertRaises(ValidationError, frappe.get_doc({
"doctype": "Batch",
diff --git a/erpnext/stock/doctype/bin/test_bin.py b/erpnext/stock/doctype/bin/test_bin.py
index 250126c6b9..ec0d8a88e3 100644
--- a/erpnext/stock/doctype/bin/test_bin.py
+++ b/erpnext/stock/doctype/bin/test_bin.py
@@ -2,13 +2,13 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.utils import _create_bin
-from erpnext.tests.utils import ERPNextTestCase
-class TestBin(ERPNextTestCase):
+class TestBin(FrappeTestCase):
def test_concurrent_inserts(self):
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index bd18e788ba..16c892128a 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -6,6 +6,7 @@
import json
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import cstr, flt, nowdate, nowtime
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -35,10 +36,9 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
)
from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
from erpnext.stock.stock_ledger import get_previous_sle
-from erpnext.tests.utils import ERPNextTestCase
-class TestDeliveryNote(ERPNextTestCase):
+class TestDeliveryNote(FrappeTestCase):
def test_over_billing_against_dn(self):
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
index 321f48b2c5..dcdff4a0f1 100644
--- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
@@ -4,6 +4,7 @@
import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, flt, now_datetime, nowdate
import erpnext
@@ -12,10 +13,10 @@ from erpnext.stock.doctype.delivery_trip.delivery_trip import (
make_expense_claim,
notify_customers,
)
-from erpnext.tests.utils import ERPNextTestCase, create_test_contact_and_address
+from erpnext.tests.utils import create_test_contact_and_address
-class TestDeliveryTrip(ERPNextTestCase):
+class TestDeliveryTrip(FrappeTestCase):
def setUp(self):
super().setUp()
driver = create_driver()
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 9491e17259..d7671b1d71 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -6,6 +6,7 @@ import json
import frappe
from frappe.test_runner import make_test_objects
+from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, today
from erpnext.controllers.item_variant import (
@@ -25,7 +26,6 @@ from erpnext.stock.doctype.item.item import (
)
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.get_item_details import get_item_details
-from erpnext.tests.utils import ERPNextTestCase, change_settings
test_ignore = ["BOM"]
test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"]
@@ -53,7 +53,7 @@ def make_item(item_code, properties=None):
return item
-class TestItem(ERPNextTestCase):
+class TestItem(FrappeTestCase):
def setUp(self):
super().setUp()
frappe.flags.attribute_values = None
diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
index 3976af4e88..501c1c1ad3 100644
--- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
@@ -4,6 +4,7 @@
import json
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt
from erpnext.buying.doctype.purchase_order.purchase_order import (
@@ -18,10 +19,9 @@ from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
create_stock_reconciliation,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestItemAlternative(ERPNextTestCase):
+class TestItemAlternative(FrappeTestCase):
def setUp(self):
super().setUp()
make_items()
diff --git a/erpnext/stock/doctype/item_attribute/test_item_attribute.py b/erpnext/stock/doctype/item_attribute/test_item_attribute.py
index 0b7ca25715..055c22e0c5 100644
--- a/erpnext/stock/doctype/item_attribute/test_item_attribute.py
+++ b/erpnext/stock/doctype/item_attribute/test_item_attribute.py
@@ -6,11 +6,12 @@ import frappe
test_records = frappe.get_test_records('Item Attribute')
+from frappe.tests.utils import FrappeTestCase
+
from erpnext.stock.doctype.item_attribute.item_attribute import ItemAttributeIncrementError
-from erpnext.tests.utils import ERPNextTestCase
-class TestItemAttribute(ERPNextTestCase):
+class TestItemAttribute(FrappeTestCase):
def setUp(self):
super().setUp()
if frappe.db.exists("Item Attribute", "_Test_Length"):
diff --git a/erpnext/stock/doctype/item_price/test_item_price.py b/erpnext/stock/doctype/item_price/test_item_price.py
index f81770e487..6ceba3f8d3 100644
--- a/erpnext/stock/doctype/item_price/test_item_price.py
+++ b/erpnext/stock/doctype/item_price/test_item_price.py
@@ -4,13 +4,13 @@
import frappe
from frappe.test_runner import make_test_records_for_doctype
+from frappe.tests.utils import FrappeTestCase
from erpnext.stock.doctype.item_price.item_price import ItemPriceDuplicateItem
from erpnext.stock.get_item_details import get_price_list_rate_for, process_args
-from erpnext.tests.utils import ERPNextTestCase
-class TestItemPrice(ERPNextTestCase):
+class TestItemPrice(FrappeTestCase):
def setUp(self):
super().setUp()
frappe.db.sql("delete from `tabItem Price`")
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index df8cadd7f8..dbaefc1e11 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -4,6 +4,7 @@
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_to_date, flt, now
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@@ -14,10 +15,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import (
get_gl_entries,
make_purchase_receipt,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestLandedCostVoucher(ERPNextTestCase):
+class TestLandedCostVoucher(FrappeTestCase):
def test_landed_cost_voucher(self):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py
index 383b0ae806..1cda781617 100644
--- a/erpnext/stock/doctype/material_request/test_material_request.py
+++ b/erpnext/stock/doctype/material_request/test_material_request.py
@@ -6,6 +6,7 @@
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt, today
from erpnext.stock.doctype.item.test_item import create_item
@@ -15,10 +16,9 @@ from erpnext.stock.doctype.material_request.material_request import (
make_supplier_quotation,
raise_work_orders,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestMaterialRequest(ERPNextTestCase):
+class TestMaterialRequest(FrappeTestCase):
def test_make_purchase_order(self):
mr = frappe.copy_doc(test_records[0]).insert()
diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py
index 2521ac9fe7..94268a8ef3 100644
--- a/erpnext/stock/doctype/packed_item/test_packed_item.py
+++ b/erpnext/stock/doctype/packed_item/test_packed_item.py
@@ -1,6 +1,7 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
+from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_to_date, nowdate
from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
@@ -9,10 +10,9 @@ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_orde
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-from erpnext.tests.utils import ERPNextTestCase, change_settings
-class TestPackedItem(ERPNextTestCase):
+class TestPackedItem(FrappeTestCase):
"Test impact on Packed Items table in various scenarios."
@classmethod
def setUpClass(cls) -> None:
diff --git a/erpnext/stock/doctype/packing_slip/test_packing_slip.py b/erpnext/stock/doctype/packing_slip/test_packing_slip.py
index 5eb6b7399a..bc405b2099 100644
--- a/erpnext/stock/doctype/packing_slip/test_packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/test_packing_slip.py
@@ -4,7 +4,7 @@
import unittest
# test_records = frappe.get_test_records('Packing Slip')
-from erpnext.tests.utils import ERPNextTestCase
+from frappe.tests.utils import FrappeTestCase
class TestPackingSlip(unittest.TestCase):
diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
index 41e3150f0d..f3b6b89784 100644
--- a/erpnext/stock/doctype/pick_list/test_pick_list.py
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -6,16 +6,17 @@ from frappe import _dict
test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch']
+from frappe.tests.utils import FrappeTestCase
+
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.pick_list.pick_list import create_delivery_note
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
EmptyStockReconciliationItemsError,
)
-from erpnext.tests.utils import ERPNextTestCase
-class TestPickList(ERPNextTestCase):
+class TestPickList(FrappeTestCase):
def test_pick_list_picks_warehouse_for_each_item(self):
try:
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d481689c13..a24acb1bd8 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -7,6 +7,7 @@ import unittest
from collections import defaultdict
import frappe
+from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, cint, cstr, flt, today
import erpnext
@@ -17,10 +18,9 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchas
from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError, get_serial_nos
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.stock_ledger import SerialNoExistsInFutureTransaction
-from erpnext.tests.utils import ERPNextTestCase, change_settings
-class TestPurchaseReceipt(ERPNextTestCase):
+class TestPurchaseReceipt(FrappeTestCase):
def setUp(self):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
diff --git a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
index ff1c19a827..4e8d71fe5e 100644
--- a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
+++ b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
@@ -2,6 +2,7 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.stock.doctype.batch.test_batch import make_new_batch
from erpnext.stock.doctype.item.test_item import make_item
@@ -9,10 +10,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.get_item_details import get_conversion_factor
-from erpnext.tests.utils import ERPNextTestCase
-class TestPutawayRule(ERPNextTestCase):
+class TestPutawayRule(FrappeTestCase):
def setUp(self):
if not frappe.db.exists("Item", "_Rice"):
make_item("_Rice", {
diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
index 308c62875d..601ca054b5 100644
--- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
@@ -2,6 +2,7 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate
from erpnext.controllers.stock_controller import (
@@ -13,12 +14,11 @@ from erpnext.controllers.stock_controller import (
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-from erpnext.tests.utils import ERPNextTestCase
# test_records = frappe.get_test_records('Quality Inspection')
-class TestQualityInspection(ERPNextTestCase):
+class TestQualityInspection(FrappeTestCase):
def setUp(self):
super().setUp()
create_item("_Test Item with QA")
diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py
index f8cea71725..057a7d4c01 100644
--- a/erpnext/stock/doctype/serial_no/test_serial_no.py
+++ b/erpnext/stock/doctype/serial_no/test_serial_no.py
@@ -18,11 +18,12 @@ from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
test_dependencies = ["Item"]
test_records = frappe.get_test_records('Serial No')
+from frappe.tests.utils import FrappeTestCase
+
from erpnext.stock.doctype.serial_no.serial_no import *
-from erpnext.tests.utils import ERPNextTestCase
-class TestSerialNo(ERPNextTestCase):
+class TestSerialNo(FrappeTestCase):
def tearDown(self):
frappe.db.rollback()
diff --git a/erpnext/stock/doctype/shipment/test_shipment.py b/erpnext/stock/doctype/shipment/test_shipment.py
index afe821845a..317abb6d03 100644
--- a/erpnext/stock/doctype/shipment/test_shipment.py
+++ b/erpnext/stock/doctype/shipment/test_shipment.py
@@ -4,12 +4,12 @@
from datetime import date, timedelta
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.stock.doctype.delivery_note.delivery_note import make_shipment
-from erpnext.tests.utils import ERPNextTestCase
-class TestShipment(ERPNextTestCase):
+class TestShipment(FrappeTestCase):
def test_shipment_from_delivery_note(self):
delivery_note = create_test_delivery_note()
delivery_note.submit()
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index c5afa49166..54c0e43c5e 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -6,6 +6,7 @@ import unittest
import frappe
from frappe.permissions import add_user_permission, remove_user_permission
+from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import flt, nowdate, nowtime
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -28,7 +29,6 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
create_stock_reconciliation,
)
from erpnext.stock.stock_ledger import NegativeStockError, get_previous_sle
-from erpnext.tests.utils import ERPNextTestCase, change_settings
def get_sle(**args):
@@ -42,7 +42,7 @@ def get_sle(**args):
order by timestamp(posting_date, posting_time) desc, creation desc limit 1"""% condition,
values, as_dict=1)
-class TestStockEntry(ERPNextTestCase):
+class TestStockEntry(FrappeTestCase):
def tearDown(self):
frappe.db.rollback()
frappe.set_user("Administrator")
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index 0864ece995..01d25b2e86 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -7,6 +7,7 @@ from uuid import uuid4
import frappe
from frappe.core.page.permission_manager.permission_manager import reset
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, today
from erpnext.stock.doctype.delivery_note.test_delivery_note import (
@@ -24,10 +25,9 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
create_stock_reconciliation,
)
from erpnext.stock.stock_ledger import get_previous_sle
-from erpnext.tests.utils import ERPNextTestCase
-class TestStockLedgerEntry(ERPNextTestCase):
+class TestStockLedgerEntry(FrappeTestCase):
def setUp(self):
items = create_items()
reset('Stock Entry')
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 2ffe127d9a..e6b252e856 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -6,6 +6,7 @@
import frappe
+from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, cstr, flt, nowdate, nowtime, random_string
from erpnext.accounts.utils import get_stock_and_account_balance
@@ -19,10 +20,9 @@ from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
from erpnext.stock.utils import get_incoming_rate, get_stock_value_on, get_valuation_method
-from erpnext.tests.utils import ERPNextTestCase, change_settings
-class TestStockReconciliation(ERPNextTestCase):
+class TestStockReconciliation(FrappeTestCase):
@classmethod
def setUpClass(cls):
create_batch_or_serial_no_items()
diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py
index 072b54b820..13496718ea 100644
--- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py
@@ -4,11 +4,10 @@
import unittest
import frappe
-
-from erpnext.tests.utils import ERPNextTestCase
+from frappe.tests.utils import FrappeTestCase
-class TestStockSettings(ERPNextTestCase):
+class TestStockSettings(FrappeTestCase):
def setUp(self):
super().setUp()
frappe.db.set_value("Stock Settings", None, "clean_description_html", 0)
diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py
index 26db2642e4..cdb771935b 100644
--- a/erpnext/stock/doctype/warehouse/test_warehouse.py
+++ b/erpnext/stock/doctype/warehouse/test_warehouse.py
@@ -3,17 +3,17 @@
import frappe
from frappe.test_runner import make_test_records
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import cint
import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-from erpnext.tests.utils import ERPNextTestCase
test_records = frappe.get_test_records('Warehouse')
-class TestWarehouse(ERPNextTestCase):
+class TestWarehouse(FrappeTestCase):
def setUp(self):
super().setUp()
if not frappe.get_value('Item', '_Test Item'):
diff --git a/erpnext/stock/report/stock_ageing/test_stock_ageing.py b/erpnext/stock/report/stock_ageing/test_stock_ageing.py
index 3fc357e8d4..2630805c62 100644
--- a/erpnext/stock/report/stock_ageing/test_stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/test_stock_ageing.py
@@ -2,12 +2,12 @@
# See license.txt
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, format_report_data
-from erpnext.tests.utils import ERPNextTestCase
-class TestStockAgeing(ERPNextTestCase):
+class TestStockAgeing(FrappeTestCase):
def setUp(self) -> None:
self.filters = frappe._dict(
company="_Test Company",
@@ -610,4 +610,4 @@ def generate_item_and_item_wh_wise_slots(filters, sle):
item_wh_wise_slots = FIFOSlots(filters, sle).generate()
filters.show_warehouse_wise_stock = False
- return item_wise_slots, item_wh_wise_slots
\ No newline at end of file
+ return item_wise_slots, item_wh_wise_slots
diff --git a/erpnext/stock/report/stock_analytics/test_stock_analytics.py b/erpnext/stock/report/stock_analytics/test_stock_analytics.py
index 32df585937..f6c98f914d 100644
--- a/erpnext/stock/report/stock_analytics/test_stock_analytics.py
+++ b/erpnext/stock/report/stock_analytics/test_stock_analytics.py
@@ -1,14 +1,13 @@
import datetime
-import unittest
from frappe import _dict
+from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.utils import get_fiscal_year
from erpnext.stock.report.stock_analytics.stock_analytics import get_period_date_ranges
-from erpnext.tests.utils import ERPNextTestCase
-class TestStockAnalyticsReport(ERPNextTestCase):
+class TestStockAnalyticsReport(FrappeTestCase):
def test_get_period_date_ranges(self):
filters = _dict(range="Monthly", from_date="2020-12-28", to_date="2021-02-06")
diff --git a/erpnext/stock/tests/test_valuation.py b/erpnext/stock/tests/test_valuation.py
index bdb768f1ad..b64ff8e28c 100644
--- a/erpnext/stock/tests/test_valuation.py
+++ b/erpnext/stock/tests/test_valuation.py
@@ -2,13 +2,13 @@ import json
import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from hypothesis import given
from hypothesis import strategies as st
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.valuation import FIFOValuation, LIFOValuation, round_off_if_near_zero
-from erpnext.tests.utils import ERPNextTestCase
qty_gen = st.floats(min_value=-1e6, max_value=1e6)
value_gen = st.floats(min_value=1, max_value=1e6)
@@ -290,7 +290,7 @@ class TestLIFOValuation(unittest.TestCase):
self.assertTotalQty(total_qty)
self.assertTotalValue(total_value)
-class TestLIFOValuationSLE(ERPNextTestCase):
+class TestLIFOValuationSLE(FrappeTestCase):
ITEM_CODE = "_Test LIFO item"
WAREHOUSE = "_Test Warehouse - _TC"
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index 40c95eb7a3..d795253665 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -1,10 +1,6 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-import copy
-import signal
-import unittest
-from contextlib import contextmanager
from typing import Any, Dict, NewType, Optional
import frappe
@@ -13,22 +9,6 @@ from frappe.core.doctype.report.report import get_report_module_dotted_path
ReportFilters = Dict[str, Any]
ReportName = NewType("ReportName", str)
-
-class ERPNextTestCase(unittest.TestCase):
- """A sane default test class for ERPNext tests."""
-
-
- @classmethod
- def setUpClass(cls) -> None:
- frappe.db.commit()
- return super().setUpClass()
-
- @classmethod
- def tearDownClass(cls) -> None:
- frappe.db.rollback()
- return super().tearDownClass()
-
-
def create_test_contact_and_address():
frappe.db.sql('delete from tabContact')
frappe.db.sql('delete from `tabContact Email`')
@@ -81,43 +61,6 @@ def create_test_contact_and_address():
contact_two.insert()
-@contextmanager
-def change_settings(doctype, settings_dict):
- """ A context manager to ensure that settings are changed before running
- function and restored after running it regardless of exceptions occured.
- This is useful in tests where you want to make changes in a function but
- don't retain those changes.
- import and use as decorator to cover full function or using `with` statement.
-
- example:
- @change_settings("Stock Settings", {"item_naming_by": "Naming Series"})
- def test_case(self):
- ...
- """
-
- try:
- settings = frappe.get_doc(doctype)
- # remember setting
- previous_settings = copy.deepcopy(settings_dict)
- for key in previous_settings:
- previous_settings[key] = getattr(settings, key)
-
- # change setting
- for key, value in settings_dict.items():
- setattr(settings, key, value)
- settings.save()
- # singles are cached by default, clear to avoid flake
- frappe.db.value_cache[settings] = {}
- yield # yield control to calling function
-
- finally:
- # restore settings
- settings = frappe.get_doc(doctype)
- for key, value in previous_settings.items():
- setattr(settings, key, value)
- settings.save()
-
-
def execute_script_report(
report_name: ReportName,
module: str,
@@ -157,24 +100,3 @@ def execute_script_report(
except Exception:
print(f"Report failed to execute with filters: {test_filter}")
raise
-
-
-
-def timeout(seconds=30, error_message="Test timed out."):
- """ Timeout decorator to ensure a test doesn't run for too long.
-
- adapted from https://stackoverflow.com/a/2282656"""
- def decorator(func):
- def _handle_timeout(signum, frame):
- raise Exception(error_message)
-
- def wrapper(*args, **kwargs):
- signal.signal(signal.SIGALRM, _handle_timeout)
- signal.alarm(seconds)
- try:
- result = func(*args, **kwargs)
- finally:
- signal.alarm(0)
- return result
- return wrapper
- return decorator
From 829c453cb616107471ed5fd6b0ef7b75bb0420e7 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Mon, 28 Feb 2022 17:12:51 +0530
Subject: [PATCH 64/64] test: remove transaction commits from buying module
---
erpnext/buying/doctype/purchase_order/test_purchase_order.py | 4 ++--
.../request_for_quotation/test_request_for_quotation.py | 4 ++--
erpnext/buying/doctype/supplier/test_supplier.py | 5 +++--
.../doctype/supplier_quotation/test_supplier_quotation.py | 4 ++--
.../doctype/supplier_scorecard/test_supplier_scorecard.py | 4 ++--
.../test_supplier_scorecard_criteria.py | 4 ++--
.../test_supplier_scorecard_variable.py | 4 ++--
.../report/procurement_tracker/test_procurement_tracker.py | 4 ++--
.../test_subcontracted_item_to_be_received.py | 4 ++--
.../test_subcontracted_raw_materials_to_be_transferred.py | 4 ++--
10 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 645e97ee7c..efa2ab1268 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -3,9 +3,9 @@
import json
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, flt, getdate, nowdate
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
@@ -27,7 +27,7 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
-class TestPurchaseOrder(unittest.TestCase):
+class TestPurchaseOrder(FrappeTestCase):
def test_make_purchase_receipt(self):
po = create_purchase_order(do_not_submit=True)
self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name)
diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
index 51901991b5..5b2112424c 100644
--- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
@@ -1,9 +1,9 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import (
@@ -16,7 +16,7 @@ from erpnext.stock.doctype.item.test_item import make_item
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
-class TestRequestforQuotation(unittest.TestCase):
+class TestRequestforQuotation(FrappeTestCase):
def test_quote_status(self):
rfq = make_request_for_quotation()
diff --git a/erpnext/buying/doctype/supplier/test_supplier.py b/erpnext/buying/doctype/supplier/test_supplier.py
index 0fb81b2578..7358e2af22 100644
--- a/erpnext/buying/doctype/supplier/test_supplier.py
+++ b/erpnext/buying/doctype/supplier/test_supplier.py
@@ -1,7 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-import unittest
import frappe
from frappe.test_runner import make_test_records
@@ -12,8 +11,10 @@ from erpnext.exceptions import PartyDisabled
test_dependencies = ['Payment Term', 'Payment Terms Template']
test_records = frappe.get_test_records('Supplier')
+from frappe.tests.utils import FrappeTestCase
-class TestSupplier(unittest.TestCase):
+
+class TestSupplier(FrappeTestCase):
def test_get_supplier_group_details(self):
doc = frappe.new_doc("Supplier Group")
doc.supplier_group_name = "_Testing Supplier Group"
diff --git a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py
index d48ac7eb3b..a4d45975c3 100644
--- a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py
+++ b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py
@@ -3,12 +3,12 @@
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
-class TestPurchaseOrder(unittest.TestCase):
+class TestPurchaseOrder(FrappeTestCase):
def test_make_purchase_order(self):
from erpnext.buying.doctype.supplier_quotation.supplier_quotation import make_purchase_order
diff --git a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py
index 7908c35cbb..8ecc2cd466 100644
--- a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py
+++ b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py
@@ -1,12 +1,12 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
-class TestSupplierScorecard(unittest.TestCase):
+class TestSupplierScorecard(FrappeTestCase):
def test_create_scorecard(self):
doc = make_supplier_scorecard().insert()
diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py
index dacc982420..7ff84c15e5 100644
--- a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py
+++ b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py
@@ -1,12 +1,12 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
-class TestSupplierScorecardCriteria(unittest.TestCase):
+class TestSupplierScorecardCriteria(FrappeTestCase):
def test_variables_exist(self):
delete_test_scorecards()
for d in test_good_criteria:
diff --git a/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py b/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py
index 4d75981125..32005a37dc 100644
--- a/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py
+++ b/erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py
@@ -1,16 +1,16 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.buying.doctype.supplier_scorecard_variable.supplier_scorecard_variable import (
VariablePathNotFound,
)
-class TestSupplierScorecardVariable(unittest.TestCase):
+class TestSupplierScorecardVariable(FrappeTestCase):
def test_variable_exist(self):
for d in test_existing_variables:
my_doc = frappe.get_doc("Supplier Scorecard Variable", d.get("name"))
diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
index 84de8c6743..44524527e3 100644
--- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
+++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
@@ -2,10 +2,10 @@
# For license information, please see license.txt
-import unittest
from datetime import datetime
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
from erpnext.buying.report.procurement_tracker.procurement_tracker import execute
@@ -14,7 +14,7 @@ from erpnext.stock.doctype.material_request.test_material_request import make_ma
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
-class TestProcurementTracker(unittest.TestCase):
+class TestProcurementTracker(FrappeTestCase):
def test_result_for_procurement_tracker(self):
filters = {
'company': '_Test Procurement Company',
diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
index 144523ad52..c2b38d38e1 100644
--- a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
+++ b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
@@ -3,9 +3,9 @@
# Compiled at: 2019-05-06 09:51:46
# Decompiled by https://python-decompiler.com
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
@@ -15,7 +15,7 @@ from erpnext.buying.report.subcontracted_item_to_be_received.subcontracted_item_
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
-class TestSubcontractedItemToBeReceived(unittest.TestCase):
+class TestSubcontractedItemToBeReceived(FrappeTestCase):
def test_pending_and_received_qty(self):
po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes')
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index 3c203ac23f..fc9acabc81 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -4,9 +4,9 @@
# Decompiled by https://python-decompiler.com
import json
-import unittest
import frappe
+from frappe.tests.utils import FrappeTestCase
from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
@@ -16,7 +16,7 @@ from erpnext.buying.report.subcontracted_raw_materials_to_be_transferred.subcont
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
-class TestSubcontractedItemToBeTransferred(unittest.TestCase):
+class TestSubcontractedItemToBeTransferred(FrappeTestCase):
def test_pending_and_transferred_qty(self):
po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes', supplier_warehouse="_Test Warehouse 1 - _TC")