Merge branch 'develop' of https://github.com/frappe/erpnext into grant_commission_check
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index bef6661..dcfad1f 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -131,11 +131,3 @@
return frappe.get_attr(overrides[function_path][-1])(*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/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 4211bd0..f3351dd 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 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
@@ -275,6 +276,10 @@
}
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 +316,114 @@
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.extend(get_ld_matching_query(bank_account, amount_condition, filters))
+
+ if transaction.deposit > 0 and "loan_repayment" in document_types:
+ 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,
+ 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_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.amount_paid,
+ 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.payment_account == bank_account
+ )
+
+ if amount_condition:
+ query.where(
+ loan_repayment.amount_paid == filters.get('amount')
+ )
+ else:
+ query.where(
+ loan_repayment.amount_paid <= filters.get('amount')
+ )
+
+ vouchers = query.run()
+
+ return vouchers
+
def get_pe_matching_query(amount_condition, account_from_to, transaction):
# get matching payment entries query
if transaction.deposit > 0:
@@ -348,7 +461,6 @@
# 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/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 51e1d6e..a476cab 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -49,7 +49,8 @@
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":
@@ -116,11 +117,18 @@
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/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index 72b6893..d84b8e0 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 @@
frappe.get_doc({
"doctype": "Bank",
"bank_name":bank_name,
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -119,7 +119,7 @@
"account_name":"Checking Account",
"bank": bank_name,
"account": account_name
- }).insert()
+ }).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -184,7 +184,7 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index ade7f81..6e7b80e 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 @@
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 6700e9b..3eaf6a2 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.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 @@
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"
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 3be3925..a9bc028 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -114,8 +114,6 @@
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 @@
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 @@
(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 @@
(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.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 02a144d..c36c843 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -91,7 +91,6 @@
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 @@
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 @@
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 @@
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()
@@ -1077,7 +1066,7 @@
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"),
@@ -1337,10 +1326,6 @@
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 @@
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 @@
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 @@
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)
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 5229d87..9b3b3aa 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -439,7 +439,6 @@
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")
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 09aa723..1b34d6d 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 @@
'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,
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 b590944..1d30934 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 @@
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 c13bc23..d6f6c5b 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -307,7 +307,7 @@
.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 @@
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/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 6c401fb..b72d266 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 @@
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_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 @@
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 @@
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 @@
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 @@
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:
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index bf668ab..621de82 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 @@
# 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/test/test_reports.py b/erpnext/accounts/test/test_reports.py
index 78c109a..4ed966d 100644
--- a/erpnext/accounts/test/test_reports.py
+++ b/erpnext/accounts/test/test_reports.py
@@ -39,10 +39,11 @@
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/accounts/utils.py b/erpnext/accounts/utils.py
index 39e84e3..b17b90b 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -847,7 +847,7 @@
"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/asset.py b/erpnext/assets/doctype/asset/asset.py
index 6e87426..ea473fa 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -417,11 +417,12 @@
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 @@
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")
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index c08dc21..ffd1065 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -873,8 +873,9 @@
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 @@
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",
@@ -1264,7 +1280,7 @@
if not args.do_not_save:
try:
- asset.save()
+ asset.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
@@ -1305,7 +1321,7 @@
"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 3d19fa3..2f52248 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 @@
})
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 13fe9df..0fb81b2 100644
--- a/erpnext/buying/doctype/supplier/test_supplier.py
+++ b/erpnext/buying/doctype/supplier/test_supplier.py
@@ -14,151 +14,150 @@
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/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index d05787f..a94af10 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1566,13 +1566,12 @@
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):
diff --git a/erpnext/controllers/employee_boarding_controller.py b/erpnext/controllers/employee_boarding_controller.py
index ae2c737..dd02ce1 100644
--- a/erpnext/controllers/employee_boarding_controller.py
+++ b/erpnext/controllers/employee_boarding_controller.py
@@ -104,11 +104,11 @@
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/domains/non_profit.py b/erpnext/domains/non_profit.py
deleted file mode 100644
index d9fc5e5..0000000
--- 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/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py
index 007bf8b..cfc3c7b 100644
--- a/erpnext/e_commerce/product_data_engine/query.py
+++ b/erpnext/e_commerce/product_data_engine/query.py
@@ -264,7 +264,7 @@
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 @@
# slice results manually
result[:self.page_length]
- return result
\ No newline at end of file
+ return result
diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py
index 458cf69..372aed0 100644
--- a/erpnext/e_commerce/shopping_cart/cart.py
+++ b/erpnext/e_commerce/shopping_cart/cart.py
@@ -310,7 +310,7 @@
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:
diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
index 8519e68..37b3672 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 @@
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
@@ -175,7 +181,7 @@
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
@@ -254,10 +260,9 @@
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/education/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
index 68e7780..4526585 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 = $('<div>')
+ .appendTo(frm.fields_dict.students_html.wrapper);
+ },
onload: function(frm) {
frm.set_query("student_group", function() {
return {
@@ -34,6 +38,7 @@
student_group: function(frm) {
if ((frm.doc.student_group && frm.doc.date) || frm.doc.course_schedule) {
+ frm.students_area.find('.student-attendance-checks').html(`<div style='padding: 2rem 0'>Fetching...</div>`);
var method = "erpnext.education.doctype.student_attendance_tool.student_attendance_tool.get_student_attendance_records";
frappe.call({
@@ -62,10 +67,6 @@
},
get_students: function(frm, students) {
- if (!frm.students_area) {
- frm.students_area = $('<div>')
- .appendTo(frm.fields_dict.students_html.wrapper);
- }
students = students || [];
frm.students_editor = new education.StudentsEditor(frm, frm.students_area, students);
}
@@ -163,16 +164,26 @@
);
});
- 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 += `<div class="col-sm-3">
+ <div class="checkbox">
+ <label>
+ <input
+ type="checkbox"
+ data-group_roll_number="${student.group_roll_number}"
+ data-student="${student.student}"
+ data-student-name="${student.student_name}"
+ class="students-check"
+ ${student.status==='Present' ? 'checked' : ''}>
+ ${student.group_roll_number} - ${student.student_name}
+ </label>
+ </div>
+ </div>`;
+ }
- $(htmls.join("")).appendTo(me.wrapper);
+ $(`<div class='student-attendance-checks'>${student_html}</div>`).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 7deb6b1..92bb20c 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 @@
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/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
index 54ed6f7..26bd19f 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 @@
"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/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py
index a4e2157..14c86d5 100644
--- a/erpnext/erpnext_integrations/taxjar_integration.py
+++ b/erpnext/erpnext_integrations/taxjar_integration.py
@@ -8,10 +8,6 @@
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 @@
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 @@
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 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 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 @@
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 @@
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 @@
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_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")
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 38fa691..f8c4288 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -68,7 +68,6 @@
'Distribution': 'erpnext.domains.distribution',
'Education': 'erpnext.domains.education',
'Manufacturing': 'erpnext.domains.manufacturing',
- 'Non Profit': 'erpnext.domains.non_profit',
'Retail': 'erpnext.domains.retail',
'Services': 'erpnext.domains.services',
}
@@ -175,7 +174,6 @@
{"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"},
]
@@ -369,7 +367,6 @@
"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": [
@@ -563,19 +560,6 @@
{'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}
- ],
}
additional_timeline_content = {
diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py
index ed0bfcf..71300c4 100644
--- a/erpnext/hr/doctype/department/department.py
+++ b/erpnext/hr/doctype/department/department.py
@@ -32,7 +32,7 @@
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):
diff --git a/erpnext/hr/doctype/department/test_records.json b/erpnext/hr/doctype/department/test_records.json
index 654925e..e3421f2 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
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index a2df26c..6e52eb9 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -142,7 +142,7 @@
"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/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
index 2d129c8..0fb821d 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 @@
# 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 @@
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 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/hr/doctype/exit_interview/exit_interview.py b/erpnext/hr/doctype/exit_interview/exit_interview.py
index 30e19f1..59fb2fd 100644
--- a/erpnext/hr/doctype/exit_interview/exit_interview.py
+++ b/erpnext/hr/doctype/exit_interview/exit_interview.py
@@ -128,4 +128,4 @@
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 acd50f2..abb2887 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 @@
"vehicle_value": flt(500000)
})
try:
- vehicle.insert()
+ vehicle.insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
return license_plate
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index 7811d56..50926d7 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",
@@ -107,11 +111,6 @@
"label": "Disbursement Details"
},
{
- "fieldname": "customer_details_section",
- "fieldtype": "Section Break",
- "label": "Customer Details"
- },
- {
"fetch_from": "against_loan.applicant_type",
"fieldname": "applicant_type",
"fieldtype": "Select",
@@ -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 df3aadf..54a03b9 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 @@
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 @@
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 @@
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 93ef217..480e010 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",
+ "payment_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": "payment_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-18 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 f3ed611..67c2b1e 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 @@
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 @@
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 @@
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 @@
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 @@
"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/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index d88e10a..2359815 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 @@
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 @@
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 ed6a029..e1120c7 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -636,6 +636,21 @@
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
diff --git a/erpnext/manufacturing/report/test_reports.py b/erpnext/manufacturing/report/test_reports.py
index 9f51ded..e436fdc 100644
--- a/erpnext/manufacturing/report/test_reports.py
+++ b/erpnext/manufacturing/report/test_reports.py
@@ -55,10 +55,11 @@
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/modules.txt b/erpnext/modules.txt
index 8c79ee5..c6b3159 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -15,7 +15,6 @@
Education
Regional
ERPNext Integrations
-Non Profit
Quality Management
Communication
Loan Management
diff --git a/erpnext/non_profit/__init__.py b/erpnext/non_profit/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/non_profit/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/__init__.py b/erpnext/non_profit/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/non_profit/doctype/__init__.py
+++ /dev/null
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 e69de29..0000000
--- a/erpnext/non_profit/doctype/certification_application/__init__.py
+++ /dev/null
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 1e6a9a4..0000000
--- 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 f562fa6..0000000
--- 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 cbbe191..0000000
--- 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 8687b4d..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/certified_consultant/__init__.py
+++ /dev/null
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 cd004c3..0000000
--- 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 d77f1b2..0000000
--- 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 47361cc..0000000
--- 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 d10353c..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/chapter/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/chapter/chapter.js b/erpnext/non_profit/doctype/chapter/chapter.js
deleted file mode 100644
index c8b6d4a..0000000
--- 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 86cba9a..0000000
--- 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 c01b1ef..0000000
--- 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 321828f..0000000
--- a/erpnext/non_profit/doctype/chapter/templates/chapter.html
+++ /dev/null
@@ -1,79 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
-<h1>{{ title }}</h1>
-<p>{{ introduction }}</p>
-{% if meetup_embed_html %}
- {{ meetup_embed_html }}
-{% endif %}
-<h3>Member Details</h3>
-
-{% if members %}
- <table class="table" style="max-width: 600px;">
- {% set index = [1] %}
- {% for user in members %}
- {% if user.enabled == 1 %}
- <tr>
- <td>
- <div style="margin-bottom: 30px; max-width: 600px" class="with-border">
- <div class="row">
- <div class="col-lg-6 col-md-6 col-sm-6">
- <div class="pull-left">
- <b>{{ index|length }}. {{ frappe.db.get_value('User', user.user, 'full_name') }}</b></div>
- </div>
- <div class="pull-right">
- {% if user.website_url %}
- <a href="{{ user.website_url }}">{{ user.website_url | truncate (50) or '' }}</a>
- {% endif %}
- </div>
- <div class="clearfix"></div>
- </div>
- <br><br>
- <div class="col-lg-12">
- {% if user.introduction %}
- {{ user.introduction }}
- {% endif %}
- </div>
- </div>
- </div>
- </td>
- </tr>
- {% set __ = index.append(1) %}
- {% endif %}
- {% endfor %}
- </table>
-{% else %}
- <p>No member yet.</p>
-{% endif %}
-
-<h3>Chapter Head</h3>
-<div style="margin-bottom: 30px; max-width: 600px" class="with-border">
-
-<table class="table table-bordered small" style="max-width: 600px;">
- {% set doc = frappe.get_doc('Member',chapter_head) %}
- <tr>
- <td style='width: 15%'>Name</td>
- <td><b>{{ doc.member_name }}<b></td>
- </tr>
- <tr>
- <td>Email</td>
- <td>{{ frappe.db.get_value('User', doc.email, 'email') or '' }}</td>
- </tr>
- <tr>
- <td>Phone</td>
- <td>{{ frappe.db.get_value('User', doc.email, 'phone') or '' }}</td>
- </tr>
-</table>
-</div>
-
-{% if address %}
-<h3>Address</h3>
-<div style="margin-bottom: 30px; max-width: 600px" class="with-border">
-<p>{{ address or ''}}</p>
-</div>
-{% endif %}
-
-<p style="margin: 20px 0 30px;"><a href="/non_profit/join-chapter?name={{ name }}" class='btn btn-primary'>Join this Chapter</a></p>
-<p style="margin: 20px 0 30px;"><a href="/non_profit/leave-chapter?name={{ name }}" class=''>Leave this Chapter</a></p>
-
-{% 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 cad34fa..0000000
--- a/erpnext/non_profit/doctype/chapter/templates/chapter_row.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% if doc.published %}
- <div style="margin-bottom: 30px; max-width: 600px" class="with-border clickable">
- <a href={{ doc.route }}>
- <h3>{{ doc.name }}</h3>
- <p>
- <span class="label"> Chapter Head : {{ frappe.db.get_value('User', chapter_head, 'full_name') }} </span>
- <span class="label">
- {% if members %}
- {% set index = [] %}
- {% for user in members %}
- {% if user.enabled == 1 %}
- {% set __ = index.append(1) %}
- {% endif %}
- {% endfor %}
- Members: {{ index|length }}
- {% else %}
- Members: 0
- {% endif %}
- </span>
- <!-- Assignment of value to global variable not working in jinja -->
- </p>
- <p>{{ html2text(doc.introduction) | truncate (200) }}</p>
- </a>
- </div>
-{% 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 98601ef..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/chapter_member/__init__.py
+++ /dev/null
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 478bfd9..0000000
--- 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 80c0446..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/donation/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/donation/donation.js b/erpnext/non_profit/doctype/donation/donation.js
deleted file mode 100644
index 10e8220..0000000
--- 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 6759569..0000000
--- 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 54bc94b..0000000
--- 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 <b>Payment Account</b> 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 492ad62..0000000
--- 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 5fa731a..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/donor/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/donor/donor.js b/erpnext/non_profit/doctype/donor/donor.js
deleted file mode 100644
index 090d5af..0000000
--- 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 72f24ef..0000000
--- 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 058321b..0000000
--- 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 31d4d29..0000000
--- 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 fe591c8..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/donor_type/__init__.py
+++ /dev/null
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 7b1fd4f..0000000
--- 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 07118fd..0000000
--- 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 17dca89..0000000
--- 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 d433733..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/grant_application/__init__.py
+++ /dev/null
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 70f319b..0000000
--- 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 2eb2087..0000000
--- 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 cc5e1b1..0000000
--- 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 ='''<a class="btn btn-primary" href="/my-grant?new=1">
- Apply for new Grant Application</a>'''
-
-@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='<p> Please Review this grant application</p><br>' + 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 52e8469..0000000
--- a/erpnext/non_profit/doctype/grant_application/templates/grant_application.html
+++ /dev/null
@@ -1,68 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
- <h1>{{ applicant_name }}</h1>
- {% if frappe.user == owner %}
- <p><a class='btn btn-primary btn-sm' href="/my-grant?name={{ name }}">Edit Grant</a></p>
- {% endif %}
- <br>
- <table class='table table-bordered small' style='max-width: 400px; margin-bottom: 0px;'>
- <tr>
- <td style='width: 38.2%'>Organization/Indvidual</td>
- <td>{{ applicant_type }}</td>
- </tr>
- <tr>
- <td>Grant Applicant Name</td>
- <td>{{ applicant_name}}</td>
- </tr>
- <tr>
- <td>Date</td>
- <td>{{ frappe.format_date(creation) }}</td>
- </tr>
- <tr>
- <td>Status</td>
- <td>{{ status }}</td>
- </tr>
- <tr>
- <td>Email</td>
- <td>{{ email }}</td>
- </tr>
- </table>
- <h2>Q. Please outline your current situation and why you are applying for a grant?</h2>
- <p> {{ grant_description }}</p>
- <h2>Q. Requested grant amount</h2>
- <p>{{ amount }}</p>
- <h2>Q. Have you recevied grant from us before?</h2>
- <p>{{ has_any_past_grant_record }}</p>
- <h3>Contact</h3>
- {% if frappe.user != 'Guest' %}
- <table class='table table-bordered small' style='max-width: 400px; margin-bottom: 0px;'>
- {% if contact_person %}
- <tr>
- <td style='width: 38.2%'>Contact Person</td>
- <td>{{ contact_person }}</td>
- </tr>
- {% endif %}
- <tr>
- <td style='width: 38.2%'>Email</td>
- <td>{{ email }}</td>
- </tr>
- </table>
- {% else %}
- <p><a href="/login">You must register and login to view contact details</a></p>
- {% endif %}
- <br>
- {% if frappe.session.user == assessment_manager %}
- {% if assessment_scale %}
- <p> Assessment Review done </p>
- {% endif %}
- {% else %}
- <p><br><a href="/my-grant?new=1" class='btn btn-primary'>Post a New Grant</a></p>
- {% endif %}
-{% endblock %}
-{% block style %}
-<link type="text/css" rel="stylesheet" href="/assets/css/non-profits.css">
-<style>
-{% if style is defined %}{{ style }}{% endif %}
-</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 e375b16..0000000
--- a/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% if doc.published %}
- <div style='margin-bottom: 30px; max-width: 600px;'
- class='with-border clickable'>
- <a href="/{{ doc.route }}">
- <h3 style='margin-top: 0px;'>{{ doc.name }}</h3>
- <p>
- <span class='label'>{{ frappe.format_date(doc.creation) }}</span>
- </p>
- </a>
- </div>
-{% 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 ef267d7..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/member/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/member/member.js b/erpnext/non_profit/doctype/member/member.js
deleted file mode 100644
index e58ec0f..0000000
--- 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 7c1baf1..0000000
--- 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 4d80e57..0000000
--- 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 0e31e3c..0000000
--- 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 8e41e7f..0000000
--- 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 46f14ed..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/membership/__init__.py
+++ /dev/null
diff --git a/erpnext/non_profit/doctype/membership/membership.js b/erpnext/non_profit/doctype/membership/membership.js
deleted file mode 100644
index 3187204..0000000
--- 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 11d32f9..0000000
--- 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.py b/erpnext/non_profit/doctype/membership/membership.py
deleted file mode 100644
index f9b295a..0000000
--- 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 <b>Debit Account</b> in {0}").format(settings_link))
-
- if not settings.company:
- frappe.throw(_("You need to set <b>Default Company</b> 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 <b>Payment Account</b> 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 <b>Send Acknowledge Email</b> 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/non_profit/doctype/membership/membership_list.js b/erpnext/non_profit/doctype/membership/membership_list.js
deleted file mode 100644
index a959159..0000000
--- 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 fbe344c..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/membership_type/__init__.py
+++ /dev/null
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 2f24276..0000000
--- 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 6ce1ecd..0000000
--- 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 b446421..0000000
--- 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 98bc087..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/non_profit_settings/__init__.py
+++ /dev/null
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 4c4ca98..0000000
--- 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. ") + `<a href='${docs_url}'>${__('ERPNext Docs')}</a>`, 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 25ff0c1..0000000
--- 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 ace6605..0000000
--- 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) + "<br><br>" + 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 51d1ba0..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/volunteer/__init__.py
+++ /dev/null
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 0a0ab2c..0000000
--- 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 ac93d8c..0000000
--- 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 08b7f87..0000000
--- 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 b44d67d..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/volunteer_skill/__init__.py
+++ /dev/null
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 7d210aa..0000000
--- 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 fe72518..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/doctype/volunteer_type/__init__.py
+++ /dev/null
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 cef27c8..0000000
--- 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 5c17505..0000000
--- 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 256b25f..0000000
--- 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 3b1ae1a..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/report/__init__.py
+++ /dev/null
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 e69de29..0000000
--- a/erpnext/non_profit/report/expiring_memberships/__init__.py
+++ /dev/null
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 be3a243..0000000
--- 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 c311057..0000000
--- 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 3ddbfdc..0000000
--- 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 47ea5f5..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/web_form/__init__.py
+++ /dev/null
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 e69de29..0000000
--- a/erpnext/non_profit/web_form/certification_application/__init__.py
+++ /dev/null
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 8b455ed..0000000
--- 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 5fda978..0000000
--- 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 02e3e93..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/web_form/certification_application_usd/__init__.py
+++ /dev/null
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 005d1dd..0000000
--- 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 266109f..0000000
--- 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 02e3e93..0000000
--- 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 e69de29..0000000
--- a/erpnext/non_profit/web_form/grant_application/__init__.py
+++ /dev/null
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 f09e540..0000000
--- 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 73c9445..0000000
--- 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 3dfb381..0000000
--- 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 fc90475..0000000
--- a/erpnext/non_profit/workspace/non_profit/non_profit.json
+++ /dev/null
@@ -1,272 +0,0 @@
-{
- "charts": [],
- "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"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\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"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.txt b/erpnext/patches.txt
index 52c29b2..12af8f8 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -332,6 +332,7 @@
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
[post_model_sync]
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
@@ -353,4 +354,6 @@
erpnext.patches.v13_0.update_exchange_rate_settings
erpnext.patches.v14_0.delete_amazon_mws_doctype
erpnext.patches.v13_0.set_work_order_qty_in_so_from_mr
+erpnext.patches.v13_0.update_accounts_in_loan_docs
erpnext.patches.v14_0.update_batch_valuation_flag
+erpnext.patches.v14_0.delete_non_profit_doctypes
\ No newline at end of file
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 0000000..5b54b25
--- /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 Non Profit domain: https://github.com/frappe/non_profit",
+ fg="yellow",
+ )
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 0000000..440f912
--- /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()
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 0000000..565b10c
--- /dev/null
+++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py
@@ -0,0 +1,63 @@
+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)
+
+ 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)
+
+ 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)
+
+ doctypes = ['Tax Exemption 80G Certificate', 'Tax Exemption 80G Certificate Detail']
+ for doctype in doctypes:
+ frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+ forms = ['grant-application', 'certification-application', 'certification-application-usd']
+ for form in forms:
+ frappe.delete_doc("Web Form", form, ignore_missing=True, force=True)
+
+ custom_records = [
+ {"doctype": "Party Type", "name": "Member"},
+ {"doctype": "Party Type", "name": "Donor"},
+ ]
+ for record in custom_records:
+ try:
+ frappe.delete_doc(record['doctype'], record['name'], ignore_missing=True)
+ except frappe.LinkExistsError:
+ pass
+
+ 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/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index f727ff4..d2a3998 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -1268,7 +1268,7 @@
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):
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index daa0f89..6a5debf 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 @@
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"
diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
index b30d983..c3be146 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 @@
{'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/public/js/bank_reconciliation_tool/dialog_manager.js b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
index ca73393..214a1be 100644
--- a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
+++ b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js
@@ -182,6 +182,12 @@
onchange: () => this.update_options(),
},
{
+ fieldtype: "Check",
+ label: "Loan Repayment",
+ fieldname: "loan_repayment",
+ onchange: () => this.update_options(),
+ },
+ {
fieldname: "column_break_5",
fieldtype: "Column Break",
},
@@ -191,7 +197,6 @@
fieldname: "sales_invoice",
onchange: () => this.update_options(),
},
-
{
fieldtype: "Check",
label: "Purchase Invoice",
@@ -199,6 +204,12 @@
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 @@
},
{
fieldtype: "Check",
- label: "Show Only Exact Amount",
- fieldname: "exact_match",
+ label: "Loan Disbursement",
+ fieldname: "loan_disbursement",
onchange: () => this.update_options(),
},
{
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 933ced0..00373a6 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -525,6 +525,7 @@
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);
@@ -2284,13 +2285,17 @@
}
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/public/js/education/student_button.html b/erpnext/public/js/education/student_button.html
deleted file mode 100644
index b64c73a..0000000
--- a/erpnext/public/js/education/student_button.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<div class="col-sm-3">
- <div class="checkbox">
- <label>
- <input
- type="checkbox"
- data-group_roll_number="{{group_roll_number}}"
- data-student="{{student}}"
- data-student-name="{{student_name}}"
- class="students-check"
- {% if status === "Present" %}
- checked
- {% endif %}
- >
- {{ group_roll_number }} - {{ student_name }}
- </label>
- </div>
-</div>
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js
index b3a68b3..8409e78 100644
--- a/erpnext/public/js/erpnext.bundle.js
+++ b/erpnext/public/js/erpnext.bundle.js
@@ -16,7 +16,6 @@
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";
diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
index 831626a..a585aa6 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 @@
}
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 @@
}
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 @@
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 0a8ba78..52236e7 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 @@
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 @@
}
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 @@
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;
diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js
index e746ce9..83b69ae 100644
--- a/erpnext/public/js/setup_wizard.js
+++ b/erpnext/public/js/setup_wizard.js
@@ -78,11 +78,11 @@
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 @@
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;
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
index 4b645b9..666043b 100644
--- a/erpnext/public/scss/shopping_cart.scss
+++ b/erpnext/public/scss/shopping_cart.scss
@@ -338,14 +338,14 @@
.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 @@
.not-wished {
cursor: pointer;
- stroke: #F47A7A !important;
+ --icon-stroke: #F47A7A !important;
&:hover {
fill: #F47A7A;
@@ -1030,7 +1030,7 @@
}
.wished {
- stroke: none;
+ --icon-stroke: none;
fill: #F47A7A !important;
}
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 e69de29..0000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py
+++ /dev/null
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 54cde9c..0000000
--- 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 9eee722..0000000
--- 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 0f08978..0000000
--- 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 6fa3b85..0000000
--- 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 e69de29..0000000
--- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py
+++ /dev/null
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 dfa817d..0000000
--- 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 bb7f07f..0000000
--- 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
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 074bd52..12b10bb 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -53,10 +53,7 @@
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',
@@ -114,7 +111,7 @@
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)
@@ -610,15 +607,6 @@
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',
@@ -713,22 +701,6 @@
'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'
- }
- ],
- 'Donor': [
- {
- 'fieldname': 'pan_number',
- 'label': 'PAN Details',
- 'fieldtype': 'Data',
- 'insert_after': 'email'
- }
- ],
'Finance Book': [
{
'fieldname': 'for_income_tax',
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 a8da0bd..0000000
--- 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 <div class=\"letter-head\">{{ letter_head }}</div>\n{%- endif %}\n\n<div>\n <h3 class=\"text-center\">{{ doc.company }} 80G Donor Certificate</h3>\n</div>\n<br><br>\n\n<div class=\"details\">\n <p> <b>{{ _(\"Certificate No. : \") }}</b> {{ doc.name }} </p>\n <p>\n \t<b>{{ _(\"Date\") }} :</b> {{ doc.get_formatted(\"date\") }}<br>\n </p>\n <br><br>\n \n <div>\n\n This is to confirm that the {{ doc.company }} received an amount of <b>{{doc.get_formatted(\"amount\")}}</b>\n from <b>{{ doc.donor_name }}</b>\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 <br><br>\n \n <p>\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n </p>\n\n </div>\n</div>\n\n<br><br>\n<p class=\"company-address text-left\"> {{doc.company_address_display }}</p>\n\n<div class=\"certificate-footer text-center\">\n <p><i>Computer generated receipt - Does not require signature</i></p><br>\n \n {% if doc.company_pan_number %}\n <p>\n <b>{{ doc.company }}'s PAN Account No :</b> {{ doc.company_pan_number }}\n <p><br>\n {% endif %}\n \n <p>\n <b>80G Number : </b> {{ doc.company_80g_number }}\n {% if doc.company_80g_wef %}\n ( w.e.f. {{ doc.get_formatted('company_80g_wef') }} )\n {% endif %}\n </p><br>\n</div>",
- "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 e69de29..0000000
--- a/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py
+++ /dev/null
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 f1b15aa..0000000
--- 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 <div class=\"letter-head\">{{ letter_head }}</div>\n{%- endif %}\n\n<div>\n <h3 class=\"text-center\">{{ doc.company }} Members 80G Donor Certificate</h3>\n <h3 class=\"text-center\">Financial Cycle {{ doc.fiscal_year }}</h3>\n</div>\n<br><br>\n\n<div class=\"details\">\n <p> <b>{{ _(\"Certificate No. : \") }}</b> {{ doc.name }} </p>\n <p>\n \t<b>{{ _(\"Date\") }} :</b> {{ doc.get_formatted(\"date\") }}<br>\n </p>\n <br><br>\n \n <div>\n This is to confirm that the {{ doc.company }} received a total amount of <b>{{doc.get_formatted(\"total\")}}</b>\n from <b>{{ doc.member_name }}</b>\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 <br><br>\n <table class=\"table table-bordered table-condensed\">\n \t<thead>\n \t\t<tr>\n \t\t\t<th >{{ _(\"Date\") }}</th>\n \t\t\t<th class=\"text-right\">{{ _(\"Amount\") }}</th>\n \t\t\t<th class=\"text-right\">{{ _(\"Invoice ID\") }}</th>\n \t\t</tr>\n \t</thead>\n \t<tbody>\n \t\t{%- for payment in doc.payments -%}\n \t\t<tr>\n \t\t\t<td> {{ payment.date }} </td>\n \t\t\t<td class=\"text-right\">{{ payment.get_formatted(\"amount\") }}</td>\n \t\t\t<td class=\"text-right\">{{ payment.invoice_id }}</td>\n \t\t</tr>\n \t\t{%- endfor -%}\n \t</tbody>\n </table>\n \n <br>\n \n <p>\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n </p>\n\n </div>\n</div>\n\n<br><br>\n<p class=\"company-address text-left\"> {{doc.company_address_display }}</p>\n\n<div class=\"certificate-footer text-center\">\n <p><i>Computer generated receipt - Does not require signature</i></p><br>\n \n {% if doc.company_pan_number %}\n <p>\n <b>{{ doc.company }}'s PAN Account No :</b> {{ doc.company_pan_number }}\n <p><br>\n {% endif %}\n \n <p>\n <b>80G Number : </b> {{ doc.company_80g_number }}\n {% if doc.company_80g_wef %}\n ( w.e.f. {{ doc.get_formatted('company_80g_wef') }} )\n {% endif %}\n </p><br>\n</div>",
- "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 e69de29..0000000
--- a/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
index 4d75e6e..1e9f6d7 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 @@
});
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"
+ });
}
});
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index cd2738a..cefa0f3 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -195,10 +195,8 @@
{'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"},
- {'doctype': "Party Type", "party_type": "Donor", "account_type": "Receivable"},
{'doctype': "Opportunity Type", "name": _("Sales")},
{'doctype': "Opportunity Type", "name": _("Support")},
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index 4441bb9..a4f2207 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -155,7 +155,7 @@
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 baa0302..613dd3f 100644
--- a/erpnext/stock/doctype/batch/test_batch.py
+++ b/erpnext/stock/doctype/batch/test_batch.py
@@ -433,14 +433,13 @@
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
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index b9e8b3f..494fb3b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -398,6 +398,7 @@
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,20 @@
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."
+ 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(
+ 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 +494,9 @@
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):
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index fd4df42..9491e17 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -15,6 +15,7 @@
get_variant,
)
from erpnext.stock.doctype.item.item import (
+ DataValidationError,
InvalidBarcode,
StockExistsForTemplate,
get_item_attribute,
@@ -388,6 +389,26 @@
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"]
+
+ # 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)
+
+ 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')
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index b39328f..51209ac 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -56,14 +56,13 @@
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 @@
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:
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 5c9da3a..324ca7a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -629,6 +629,12 @@
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/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 6c6513b..c5afa49 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 @@
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 @@
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")
@@ -689,6 +691,8 @@
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",
@@ -1023,13 +1027,10 @@
# 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
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 df65706..83aed90 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
diff --git a/erpnext/stock/report/test_reports.py b/erpnext/stock/report/test_reports.py
index 525af40..76c2079 100644
--- a/erpnext/stock/report/test_reports.py
+++ b/erpnext/stock/report/test_reports.py
@@ -73,10 +73,11 @@
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,
+ )
diff --git a/erpnext/stock/spec/README.md b/erpnext/stock/spec/README.md
new file mode 100644
index 0000000..f5a3501
--- /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 0000000..b0d59fe
--- /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
diff --git a/erpnext/templates/includes/navbar/navbar_items.html b/erpnext/templates/includes/navbar/navbar_items.html
index 3275521..d7adae5 100644
--- a/erpnext/templates/includes/navbar/navbar_items.html
+++ b/erpnext/templates/includes/navbar/navbar_items.html
@@ -13,7 +13,7 @@
<li class="wishlist wishlist-icon hidden">
<a class="nav-link" href="/wishlist">
<svg class="icon icon-lg">
- <use href="#icon-heart-active"></use>
+ <use href="#icon-heart"></use>
</svg>
<span class="badge badge-primary shopping-badge" id="wish-count"></span>
</a>
diff --git a/erpnext/templates/pages/non_profit/__init__.py b/erpnext/templates/pages/non_profit/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/templates/pages/non_profit/__init__.py
+++ /dev/null
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 4923efc..0000000
--- 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() %}
- <p><a href="/{{ chapter.route }}" class='btn btn-primary'>
- Go to Chapter Page</a></p>
-{% endmacro %}
-{% if frappe.session.user=='Guest' %}
- <p>Please signup and login to join this chapter</p>
- <p><a href="/login?redirect-to=/{{ chapter.route }}" class='btn btn-primary'>Login</a></p>
-{% else %}
- {% if already_member %}
- <p>You are already a member of {{ chapter.name }}!</p>
- {{ chapter_button() }}
- <p><a href="">Leave Chapter</a></p>
- {% else %}
- {% if request.method=='POST' %}
- <p>Welcome to chapter {{ chapter.name }}!</p>
- {{ chapter_button() }}
- {% else %}
- <div style="padding: 20px 0;">
- <div class="row">
- <div class="col-lg-8 col-md-8">
- <form name="user-intro" action="/non_profit/join-chapter" method='POST'>
- <div class="form-group">
- <input name="name" class="hidden form-control" type="text"
- value="{{chapter.name}}">
- <input name="csrf_token" class="hidden form-control" type="text"
- value="{{frappe.session.csrf_token}}">
- </div>
- <div class="form-group">
- <label for="user" class="">User Name</label>
- <input name="user" class="form-control" type="text" value="{{ frappe.session.user }}">
- </div>
- <div class="form-group">
- <label for="website_url" class="">Website URL</label>
- <input name="website_url" required class="form-control" type="text"
- placeholder="https://example.com" />
- </div>
- <div class="form-group">
- <label for="introduction" class="">Introduction</label>
- <textarea name="introduction" required class="form-control"
- placeholder="Your profession and how you are associated with ERPNext"></textarea>
- </div>
- <div class="form-group">
- <button type="Submit" id="update_member" class="btn btn-primary">
- Submit</button>
- </div>
- </form>
- </div>
- </div>
- </div>
- {% 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 e2bc8bc..0000000
--- 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 7caf87d..0000000
--- 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 fd7658b..0000000
--- 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 %}
- <p>You are not a member of {{ chapter.name }}!</p>
- <div>
- <form>
- <div class="form-group">
- <label for="leave">Why do you want to leave this chapter</label>
- <input type="text" name="leave" class="form-control" id="leave">
- </div>
- <button type="button" class="btn btn-light btn-leave" data-title= "{{ chapter.name }}" id="btn-leave">Submit
- </button>
- </form>
- </div>
- <p>Please signup and login to join this chapter</p>
-
- <p><a href="/join-chapter?name={{ chapter.name }}" class='btn btn-primary'>Become Member agian</a></p>
- {% endif %}
- <script>
- frappe.ready(function() {
- $(".btn-leave").on("click", function() {
- var leave = $("#leave").val();
- var user_id = frappe.session.user;
- var title = $(this).attr("data-title");
- frappe.call({
- method: "erpnext.non_profit.doctype.chapter.chapter.leave",
- args: {
- leave_reason: leave,
- user_id: user_id,
- title: title
- },
- callback: function(r) {
- if(r.message) {
- frappe.msgprint(r.message)
- }
- }
- })
- });
- })
- </script>
-{% 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 65908e1..0000000
--- 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
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index 2bd7e9e..40c95eb 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -66,6 +66,20 @@
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):
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index f345a87..b882b9d 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -3731,7 +3731,7 @@
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 @@
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.",
diff --git a/erpnext/www/lms/macros/hero.html b/erpnext/www/lms/macros/hero.html
index e72bfc8..95ba8f7 100644
--- a/erpnext/www/lms/macros/hero.html
+++ b/erpnext/www/lms/macros/hero.html
@@ -11,7 +11,7 @@
{% if frappe.session.user == 'Guest' %}
<a id="signup" class="btn btn-primary btn-lg" href="/login#signup">{{_('Sign Up')}}</a>
{% elif not has_access %}
- <button id="enroll" class="btn btn-primary btn-lg" onclick="enroll()" disabled>{{_('Enroll')}}</button>
+ <button id="enroll" class="btn btn-primary btn-lg" onclick="enroll()">{{_('Enroll')}}</button>
{% endif %}
</p>
</div>
@@ -20,34 +20,35 @@
<script type="text/javascript">
frappe.ready(() => {
btn = document.getElementById('enroll');
- if (btn) btn.disabled = false;
})
function enroll() {
let params = frappe.utils.get_query_params()
let btn = document.getElementById('enroll');
- btn.disbaled = true;
- btn.innerText = __('Enrolling...')
let opts = {
method: 'erpnext.education.utils.enroll_in_program',
args: {
program_name: params.program
- }
+ },
+ freeze: true,
+ freeze_message: __('Enrolling...')
}
frappe.call(opts).then(res => {
let success_dialog = new frappe.ui.Dialog({
title: __('Success'),
+ primary_action_label: __('View Program Content'),
+ primary_action: function() {
+ window.location.reload();
+ },
secondary_action: function() {
- window.location.reload()
+ window.location.reload();
}
})
- success_dialog.set_message(__('You have successfully enrolled for the program '));
- success_dialog.$message.show()
success_dialog.show();
- btn.disbaled = false;
+ success_dialog.set_message(__('You have successfully enrolled for the program '));
})
}
</script>
diff --git a/erpnext/www/shop-by-category/index.py b/erpnext/www/shop-by-category/index.py
index 3946212..09f97ba 100644
--- a/erpnext/www/shop-by-category/index.py
+++ b/erpnext/www/shop-by-category/index.py
@@ -62,8 +62,7 @@
"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 @@
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