Merge branch 'develop' into ordered-qty-for-packed-items
This commit is contained in:
commit
cde711151e
@ -131,11 +131,3 @@ def allow_regional(fn):
|
|||||||
return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs)
|
return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs)
|
||||||
|
|
||||||
return caller
|
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]
|
|
||||||
|
@ -7,6 +7,7 @@ import json
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
from erpnext import get_company_currency
|
from erpnext import get_company_currency
|
||||||
@ -275,6 +276,10 @@ def check_matching(bank_account, company, transaction, document_types):
|
|||||||
}
|
}
|
||||||
|
|
||||||
matching_vouchers = []
|
matching_vouchers = []
|
||||||
|
|
||||||
|
matching_vouchers.extend(get_loan_vouchers(bank_account, transaction,
|
||||||
|
document_types, filters))
|
||||||
|
|
||||||
for query in subquery:
|
for query in subquery:
|
||||||
matching_vouchers.extend(
|
matching_vouchers.extend(
|
||||||
frappe.db.sql(query, filters,)
|
frappe.db.sql(query, filters,)
|
||||||
@ -311,6 +316,114 @@ def get_queries(bank_account, company, transaction, document_types):
|
|||||||
|
|
||||||
return queries
|
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):
|
def get_pe_matching_query(amount_condition, account_from_to, transaction):
|
||||||
# get matching payment entries query
|
# get matching payment entries query
|
||||||
if transaction.deposit > 0:
|
if transaction.deposit > 0:
|
||||||
@ -348,7 +461,6 @@ def get_je_matching_query(amount_condition, transaction):
|
|||||||
# We have mapping at the bank level
|
# We have mapping at the bank level
|
||||||
# So one bank could have both types of bank accounts like asset and liability
|
# 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
|
# 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"
|
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
|
||||||
|
|
||||||
return f"""
|
return f"""
|
||||||
|
@ -49,7 +49,8 @@ class BankTransaction(StatusUpdater):
|
|||||||
|
|
||||||
def clear_linked_payment_entries(self, for_cancel=False):
|
def clear_linked_payment_entries(self, for_cancel=False):
|
||||||
for payment_entry in self.payment_entries:
|
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)
|
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Sales Invoice":
|
elif payment_entry.payment_document == "Sales Invoice":
|
||||||
@ -116,11 +117,18 @@ def get_paid_amount(payment_entry, currency, bank_account):
|
|||||||
payment_entry.payment_entry, paid_amount_field)
|
payment_entry.payment_entry, paid_amount_field)
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Journal Entry":
|
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":
|
elif payment_entry.payment_document == "Expense Claim":
|
||||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
|
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:
|
else:
|
||||||
frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))
|
frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
|||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Bank",
|
"doctype": "Bank",
|
||||||
"bank_name":bank_name,
|
"bank_name":bank_name,
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
|||||||
"account_name":"Checking Account",
|
"account_name":"Checking Account",
|
||||||
"bank": bank_name,
|
"bank": bank_name,
|
||||||
"account": account_name
|
"account": account_name
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ def add_vouchers():
|
|||||||
"supplier_group":"All Supplier Groups",
|
"supplier_group":"All Supplier Groups",
|
||||||
"supplier_type": "Company",
|
"supplier_type": "Company",
|
||||||
"supplier_name": "Conrad Electronic"
|
"supplier_name": "Conrad Electronic"
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
|
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
@ -203,7 +203,7 @@ def add_vouchers():
|
|||||||
"supplier_group":"All Supplier Groups",
|
"supplier_group":"All Supplier Groups",
|
||||||
"supplier_type": "Company",
|
"supplier_type": "Company",
|
||||||
"supplier_name": "Mr G"
|
"supplier_name": "Mr G"
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ def add_vouchers():
|
|||||||
"supplier_group":"All Supplier Groups",
|
"supplier_group":"All Supplier Groups",
|
||||||
"supplier_type": "Company",
|
"supplier_type": "Company",
|
||||||
"supplier_name": "Poore Simon's"
|
"supplier_name": "Poore Simon's"
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ def add_vouchers():
|
|||||||
"customer_group":"All Customer Groups",
|
"customer_group":"All Customer Groups",
|
||||||
"customer_type": "Company",
|
"customer_type": "Company",
|
||||||
"customer_name": "Poore Simon's"
|
"customer_name": "Poore Simon's"
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ def add_vouchers():
|
|||||||
"customer_group":"All Customer Groups",
|
"customer_group":"All Customer Groups",
|
||||||
"customer_type": "Company",
|
"customer_type": "Company",
|
||||||
"customer_name": "Fayva"
|
"customer_name": "Fayva"
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ class OpeningInvoiceCreationTool(Document):
|
|||||||
frappe.scrub(row.party_type): row.party,
|
frappe.scrub(row.party_type): row.party,
|
||||||
"is_pos": 0,
|
"is_pos": 0,
|
||||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
|
"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,
|
"invoice_number": row.invoice_number,
|
||||||
"disable_rounded_total": 1
|
"disable_rounded_total": 1
|
||||||
})
|
})
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# See license.txt
|
# See license.txt
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
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 (
|
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import (
|
||||||
create_dimension,
|
create_dimension,
|
||||||
@ -14,14 +10,17 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp
|
|||||||
from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import (
|
from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import (
|
||||||
get_temporary_opening_account,
|
get_temporary_opening_account,
|
||||||
)
|
)
|
||||||
|
from erpnext.tests.utils import ERPNextTestCase
|
||||||
|
|
||||||
test_dependencies = ["Customer", "Supplier", "Accounting Dimension"]
|
test_dependencies = ["Customer", "Supplier", "Accounting Dimension"]
|
||||||
|
|
||||||
class TestOpeningInvoiceCreationTool(unittest.TestCase):
|
class TestOpeningInvoiceCreationTool(ERPNextTestCase):
|
||||||
def setUp(self):
|
@classmethod
|
||||||
|
def setUpClass(self):
|
||||||
if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
|
if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
|
||||||
make_company()
|
make_company()
|
||||||
create_dimension()
|
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):
|
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")
|
doc = frappe.get_single("Opening Invoice Creation Tool")
|
||||||
@ -31,26 +30,20 @@ class TestOpeningInvoiceCreationTool(unittest.TestCase):
|
|||||||
return doc.make_invoices()
|
return doc.make_invoices()
|
||||||
|
|
||||||
def test_opening_sales_invoice_creation(self):
|
def test_opening_sales_invoice_creation(self):
|
||||||
property_setter = make_property_setter("Sales Invoice", "update_stock", "default", 1, "Check")
|
invoices = self.make_invoices(company="_Test Opening Invoice Company")
|
||||||
try:
|
|
||||||
invoices = self.make_invoices(company="_Test Opening Invoice Company")
|
|
||||||
|
|
||||||
self.assertEqual(len(invoices), 2)
|
self.assertEqual(len(invoices), 2)
|
||||||
expected_value = {
|
expected_value = {
|
||||||
"keys": ["customer", "outstanding_amount", "status"],
|
"keys": ["customer", "outstanding_amount", "status"],
|
||||||
0: ["_Test Customer", 300, "Overdue"],
|
0: ["_Test Customer", 300, "Overdue"],
|
||||||
1: ["_Test Customer 1", 250, "Overdue"],
|
1: ["_Test Customer 1", 250, "Overdue"],
|
||||||
}
|
}
|
||||||
self.check_expected_values(invoices, expected_value)
|
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
|
# Check if update stock is not enabled
|
||||||
self.assertEqual(si.update_stock, 0)
|
self.assertEqual(si.update_stock, 0)
|
||||||
|
|
||||||
finally:
|
|
||||||
property_setter.delete()
|
|
||||||
clear_doctype_cache("Sales Invoice")
|
|
||||||
|
|
||||||
def check_expected_values(self, invoices, expected_value, invoice_type="Sales"):
|
def check_expected_values(self, invoices, expected_value, invoice_type="Sales"):
|
||||||
doctype = "Sales Invoice" if invoice_type == "Sales" else "Purchase Invoice"
|
doctype = "Sales Invoice" if invoice_type == "Sales" else "Purchase Invoice"
|
||||||
|
@ -114,8 +114,6 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
var doctypes = ["Expense Claim", "Journal Entry"];
|
var doctypes = ["Expense Claim", "Journal Entry"];
|
||||||
} else if (frm.doc.party_type == "Student") {
|
} else if (frm.doc.party_type == "Student") {
|
||||||
var doctypes = ["Fees"];
|
var doctypes = ["Fees"];
|
||||||
} else if (frm.doc.party_type == "Donor") {
|
|
||||||
var doctypes = ["Donation"];
|
|
||||||
} else {
|
} else {
|
||||||
var doctypes = ["Journal Entry"];
|
var doctypes = ["Journal Entry"];
|
||||||
}
|
}
|
||||||
@ -144,7 +142,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
const child = locals[cdt][cdn];
|
const child = locals[cdt][cdn];
|
||||||
const filters = {"docstatus": 1, "company": doc.company};
|
const filters = {"docstatus": 1, "company": doc.company};
|
||||||
const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
|
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)) {
|
if (in_list(party_type_doctypes, child.reference_doctype)) {
|
||||||
filters[doc.party_type.toLowerCase()] = doc.party;
|
filters[doc.party_type.toLowerCase()] = doc.party;
|
||||||
@ -747,8 +745,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
(frm.doc.payment_type=="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=="Supplier") ||
|
||||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
|
(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=="Student")
|
||||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
|
|
||||||
) {
|
) {
|
||||||
if(total_positive_outstanding > total_negative_outstanding)
|
if(total_positive_outstanding > total_negative_outstanding)
|
||||||
if (!frm.doc.paid_amount)
|
if (!frm.doc.paid_amount)
|
||||||
@ -791,8 +788,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
(frm.doc.payment_type=="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=="Supplier") ||
|
||||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
|
(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=="Student")
|
||||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
|
|
||||||
) {
|
) {
|
||||||
if(total_positive_outstanding_including_order > paid_amount) {
|
if(total_positive_outstanding_including_order > paid_amount) {
|
||||||
var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
|
var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
|
||||||
@ -951,12 +947,6 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx]));
|
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx]));
|
||||||
return false;
|
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) {
|
if (row) {
|
||||||
|
@ -91,7 +91,6 @@ class PaymentEntry(AccountsController):
|
|||||||
self.update_expense_claim()
|
self.update_expense_claim()
|
||||||
self.update_outstanding_amounts()
|
self.update_outstanding_amounts()
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_donation()
|
|
||||||
self.update_payment_schedule()
|
self.update_payment_schedule()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
@ -101,7 +100,6 @@ class PaymentEntry(AccountsController):
|
|||||||
self.update_expense_claim()
|
self.update_expense_claim()
|
||||||
self.update_outstanding_amounts()
|
self.update_outstanding_amounts()
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_donation(cancel=1)
|
|
||||||
self.delink_advance_entry_references()
|
self.delink_advance_entry_references()
|
||||||
self.update_payment_schedule(cancel=1)
|
self.update_payment_schedule(cancel=1)
|
||||||
self.set_payment_req_status()
|
self.set_payment_req_status()
|
||||||
@ -284,8 +282,6 @@ class PaymentEntry(AccountsController):
|
|||||||
valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity")
|
valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity")
|
||||||
elif self.party_type == "Shareholder":
|
elif self.party_type == "Shareholder":
|
||||||
valid_reference_doctypes = ("Journal Entry")
|
valid_reference_doctypes = ("Journal Entry")
|
||||||
elif self.party_type == "Donor":
|
|
||||||
valid_reference_doctypes = ("Donation")
|
|
||||||
|
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if not d.allocated_amount:
|
if not d.allocated_amount:
|
||||||
@ -843,13 +839,6 @@ class PaymentEntry(AccountsController):
|
|||||||
else:
|
else:
|
||||||
update_reimbursed_amount(doc, d.allocated_amount)
|
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):
|
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||||
self.reference_no = reference_doc.name
|
self.reference_no = reference_doc.name
|
||||||
self.reference_date = nowdate()
|
self.reference_date = nowdate()
|
||||||
@ -1077,7 +1066,7 @@ def get_outstanding_reference_documents(args):
|
|||||||
if d.voucher_type in ("Purchase Invoice"):
|
if d.voucher_type in ("Purchase Invoice"):
|
||||||
d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
|
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 = []
|
orders_to_be_billed = []
|
||||||
if (args.get("party_type") != "Student"):
|
if (args.get("party_type") != "Student"):
|
||||||
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"),
|
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"),
|
||||||
@ -1337,10 +1326,6 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
|||||||
total_amount = ref_doc.get("grand_total")
|
total_amount = ref_doc.get("grand_total")
|
||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
outstanding_amount = ref_doc.get("outstanding_amount")
|
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":
|
elif reference_doctype == "Dunning":
|
||||||
total_amount = ref_doc.get("dunning_amount")
|
total_amount = ref_doc.get("dunning_amount")
|
||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
@ -1611,8 +1596,6 @@ def set_party_type(dt):
|
|||||||
party_type = "Employee"
|
party_type = "Employee"
|
||||||
elif dt == "Fees":
|
elif dt == "Fees":
|
||||||
party_type = "Student"
|
party_type = "Student"
|
||||||
elif dt == "Donation":
|
|
||||||
party_type = "Donor"
|
|
||||||
return party_type
|
return party_type
|
||||||
|
|
||||||
def set_party_account(dt, dn, doc, party_type):
|
def set_party_account(dt, dn, doc, party_type):
|
||||||
@ -1640,7 +1623,7 @@ def set_party_account_currency(dt, party_account, doc):
|
|||||||
return party_account_currency
|
return party_account_currency
|
||||||
|
|
||||||
def set_payment_type(dt, doc):
|
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):
|
or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
|
||||||
payment_type = "Receive"
|
payment_type = "Receive"
|
||||||
else:
|
else:
|
||||||
@ -1673,9 +1656,6 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre
|
|||||||
elif dt == "Dunning":
|
elif dt == "Dunning":
|
||||||
grand_total = doc.grand_total
|
grand_total = doc.grand_total
|
||||||
outstanding_amount = doc.grand_total
|
outstanding_amount = doc.grand_total
|
||||||
elif dt == "Donation":
|
|
||||||
grand_total = doc.amount
|
|
||||||
outstanding_amount = doc.amount
|
|
||||||
elif dt == "Gratuity":
|
elif dt == "Gratuity":
|
||||||
grand_total = doc.amount
|
grand_total = doc.amount
|
||||||
outstanding_amount = flt(doc.amount) - flt(doc.paid_amount)
|
outstanding_amount = flt(doc.amount) - flt(doc.paid_amount)
|
||||||
|
@ -439,7 +439,6 @@ class POSInvoice(SalesInvoice):
|
|||||||
self.paid_amount = 0
|
self.paid_amount = 0
|
||||||
|
|
||||||
def set_account_for_mode_of_payment(self):
|
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:
|
for pay in self.payments:
|
||||||
if not pay.account:
|
if not pay.account:
|
||||||
pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account")
|
pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account")
|
||||||
|
@ -46,7 +46,7 @@ def valdiate_taxes_and_charges_template(doc):
|
|||||||
|
|
||||||
for tax in doc.get("taxes"):
|
for tax in doc.get("taxes"):
|
||||||
validate_taxes_and_charges(tax)
|
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_cost_center(tax, doc)
|
||||||
validate_inclusive_tax(tax, doc)
|
validate_inclusive_tax(tax, doc)
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ def validate_party_gle_currency(party_type, party, company, party_account_curren
|
|||||||
.format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency)
|
.format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency)
|
||||||
|
|
||||||
def validate_party_accounts(doc):
|
def validate_party_accounts(doc):
|
||||||
|
from erpnext.controllers.accounts_controller import validate_account_head
|
||||||
companies = []
|
companies = []
|
||||||
|
|
||||||
for account in doc.get("accounts"):
|
for account in doc.get("accounts"):
|
||||||
@ -330,6 +330,9 @@ def validate_party_accounts(doc):
|
|||||||
if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency:
|
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"))
|
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()
|
@frappe.whitelist()
|
||||||
def get_due_date(posting_date, party_type, party, company=None, bill_date=None):
|
def get_due_date(posting_date, party_type, party, company=None, bill_date=None):
|
||||||
|
@ -4,7 +4,12 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
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):
|
def execute(filters=None):
|
||||||
@ -18,7 +23,6 @@ def execute(filters=None):
|
|||||||
|
|
||||||
data = get_entries(filters)
|
data = get_entries(filters)
|
||||||
|
|
||||||
from erpnext.accounts.utils import get_balance_on
|
|
||||||
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
||||||
|
|
||||||
total_debit, total_credit = 0,0
|
total_debit, total_credit = 0,0
|
||||||
@ -118,7 +122,21 @@ def get_columns():
|
|||||||
]
|
]
|
||||||
|
|
||||||
def get_entries(filters):
|
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,
|
select "Journal Entry" as payment_document, jv.posting_date,
|
||||||
jv.name as payment_entry, jvd.debit_in_account_currency as debit,
|
jv.name as payment_entry, jvd.debit_in_account_currency as debit,
|
||||||
jvd.credit_in_account_currency as credit, jvd.against_account,
|
jvd.credit_in_account_currency as credit, jvd.against_account,
|
||||||
@ -130,7 +148,8 @@ def get_entries(filters):
|
|||||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
||||||
and ifnull(jv.is_opening, 'No') = 'No'""", filters, as_dict=1)
|
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
|
select
|
||||||
"Payment Entry" as payment_document, name as payment_entry,
|
"Payment Entry" as payment_document, name as payment_entry,
|
||||||
reference_no, reference_date as ref_date,
|
reference_no, reference_date as ref_date,
|
||||||
@ -145,9 +164,8 @@ def get_entries(filters):
|
|||||||
and ifnull(clearance_date, '4000-01-01') > %(report_date)s
|
and ifnull(clearance_date, '4000-01-01') > %(report_date)s
|
||||||
""", filters, as_dict=1)
|
""", filters, as_dict=1)
|
||||||
|
|
||||||
pos_entries = []
|
def get_pos_entries(filters):
|
||||||
if filters.include_pos_transactions:
|
return frappe.db.sql("""
|
||||||
pos_entries = frappe.db.sql("""
|
|
||||||
select
|
select
|
||||||
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
"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,
|
si.posting_date, si.debit_to as against_account, sip.clearance_date,
|
||||||
@ -161,8 +179,42 @@ def get_entries(filters):
|
|||||||
si.posting_date ASC, si.name DESC
|
si.posting_date ASC, si.name DESC
|
||||||
""", filters, as_dict=1)
|
""", filters, as_dict=1)
|
||||||
|
|
||||||
return sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
def get_loan_entries(filters):
|
||||||
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
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):
|
def get_amounts_not_reflected_in_system(filters):
|
||||||
je_amount = frappe.db.sql("""
|
je_amount = frappe.db.sql("""
|
||||||
@ -182,7 +234,40 @@ def get_amounts_not_reflected_in_system(filters):
|
|||||||
|
|
||||||
pe_amount = flt(pe_amount[0][0]) if pe_amount else 0.0
|
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):
|
def get_balance_row(label, amount, account_currency):
|
||||||
if amount > 0:
|
if amount > 0:
|
||||||
|
@ -61,7 +61,7 @@ class TestTaxDetail(unittest.TestCase):
|
|||||||
# Create GL Entries:
|
# Create GL Entries:
|
||||||
db_doc.submit()
|
db_doc.submit()
|
||||||
else:
|
else:
|
||||||
db_doc.insert()
|
db_doc.insert(ignore_if_duplicate=True)
|
||||||
except frappe.exceptions.DuplicateEntryError:
|
except frappe.exceptions.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -39,10 +39,11 @@ class TestReports(unittest.TestCase):
|
|||||||
def test_execute_all_accounts_reports(self):
|
def test_execute_all_accounts_reports(self):
|
||||||
"""Test that all script report in stock modules are executable with supported filters"""
|
"""Test that all script report in stock modules are executable with supported filters"""
|
||||||
for report, filter in REPORT_FILTER_TEST_CASES:
|
for report, filter in REPORT_FILTER_TEST_CASES:
|
||||||
execute_script_report(
|
with self.subTest(report=report):
|
||||||
report_name=report,
|
execute_script_report(
|
||||||
module="Accounts",
|
report_name=report,
|
||||||
filters=filter,
|
module="Accounts",
|
||||||
default_filters=DEFAULT_FILTERS,
|
filters=filter,
|
||||||
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
default_filters=DEFAULT_FILTERS,
|
||||||
)
|
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
||||||
|
)
|
||||||
|
@ -847,7 +847,7 @@ def create_payment_gateway_account(gateway, payment_channel="Email"):
|
|||||||
"payment_account": bank_account.name,
|
"payment_account": bank_account.name,
|
||||||
"currency": bank_account.account_currency,
|
"currency": bank_account.account_currency,
|
||||||
"payment_channel": payment_channel
|
"payment_channel": payment_channel
|
||||||
}).insert(ignore_permissions=True)
|
}).insert(ignore_permissions=True, ignore_if_duplicate=True)
|
||||||
|
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
# already exists, due to a reinstall?
|
# already exists, due to a reinstall?
|
||||||
|
@ -1280,7 +1280,7 @@ def create_asset(**args):
|
|||||||
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
try:
|
try:
|
||||||
asset.save()
|
asset.insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -1321,7 +1321,7 @@ def create_fixed_asset_item(item_code=None, auto_create_assets=1, is_grouped_ass
|
|||||||
"is_grouped_asset": is_grouped_asset,
|
"is_grouped_asset": is_grouped_asset,
|
||||||
"asset_naming_series": naming_series
|
"asset_naming_series": naming_series
|
||||||
})
|
})
|
||||||
item.insert()
|
item.insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
return item
|
return item
|
||||||
|
@ -23,7 +23,7 @@ class TestAssetCategory(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
asset_category.insert()
|
asset_category.insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -14,151 +14,150 @@ test_records = frappe.get_test_records('Supplier')
|
|||||||
|
|
||||||
|
|
||||||
class TestSupplier(unittest.TestCase):
|
class TestSupplier(unittest.TestCase):
|
||||||
def test_get_supplier_group_details(self):
|
def test_get_supplier_group_details(self):
|
||||||
doc = frappe.new_doc("Supplier Group")
|
doc = frappe.new_doc("Supplier Group")
|
||||||
doc.supplier_group_name = "_Testing Supplier Group"
|
doc.supplier_group_name = "_Testing Supplier Group"
|
||||||
doc.payment_terms = "_Test Payment Term Template 3"
|
doc.payment_terms = "_Test Payment Term Template 3"
|
||||||
doc.accounts = []
|
doc.accounts = []
|
||||||
test_account_details = {
|
test_account_details = {
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"account": "Creditors - _TC",
|
"account": "Creditors - _TC",
|
||||||
}
|
}
|
||||||
doc.append("accounts", test_account_details)
|
doc.append("accounts", test_account_details)
|
||||||
doc.save()
|
doc.save()
|
||||||
s_doc = frappe.new_doc("Supplier")
|
s_doc = frappe.new_doc("Supplier")
|
||||||
s_doc.supplier_name = "Testing Supplier"
|
s_doc.supplier_name = "Testing Supplier"
|
||||||
s_doc.supplier_group = "_Testing Supplier Group"
|
s_doc.supplier_group = "_Testing Supplier Group"
|
||||||
s_doc.payment_terms = ""
|
s_doc.payment_terms = ""
|
||||||
s_doc.accounts = []
|
s_doc.accounts = []
|
||||||
s_doc.insert()
|
s_doc.insert()
|
||||||
s_doc.get_supplier_group_details()
|
s_doc.get_supplier_group_details()
|
||||||
self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3")
|
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].company, "_Test Company")
|
||||||
self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC")
|
self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC")
|
||||||
s_doc.delete()
|
s_doc.delete()
|
||||||
doc.delete()
|
doc.delete()
|
||||||
|
|
||||||
def test_supplier_default_payment_terms(self):
|
def test_supplier_default_payment_terms(self):
|
||||||
# Payment Term based on Days after invoice date
|
# Payment Term based on Days after invoice date
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 3")
|
"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")
|
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2016-02-21")
|
self.assertEqual(due_date, "2016-02-21")
|
||||||
|
|
||||||
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2017-02-21")
|
self.assertEqual(due_date, "2017-02-21")
|
||||||
|
|
||||||
# Payment Term based on last day of month
|
# Payment Term based on last day of month
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 1")
|
"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")
|
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2016-02-29")
|
self.assertEqual(due_date, "2016-02-29")
|
||||||
|
|
||||||
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2017-02-28")
|
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
|
# 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")
|
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")
|
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2016-02-21")
|
self.assertEqual(due_date, "2016-02-21")
|
||||||
|
|
||||||
# Payment terms for Supplier Group instead of supplier and evaluate the due date
|
# 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")
|
frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 1")
|
||||||
|
|
||||||
# Leap year
|
# Leap year
|
||||||
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
|
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2016-02-29")
|
self.assertEqual(due_date, "2016-02-29")
|
||||||
# # Non Leap year
|
# # Non Leap year
|
||||||
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1")
|
||||||
self.assertEqual(due_date, "2017-02-28")
|
self.assertEqual(due_date, "2017-02-28")
|
||||||
|
|
||||||
# Supplier with no default Payment Terms Template
|
# Supplier with no default Payment Terms Template
|
||||||
frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "")
|
frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "")
|
||||||
frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "")
|
frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "")
|
||||||
|
|
||||||
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier")
|
due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier")
|
||||||
self.assertEqual(due_date, "2016-01-22")
|
self.assertEqual(due_date, "2016-01-22")
|
||||||
# # Non Leap year
|
# # Non Leap year
|
||||||
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier")
|
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier")
|
||||||
self.assertEqual(due_date, "2017-01-22")
|
self.assertEqual(due_date, "2017-01-22")
|
||||||
|
|
||||||
def test_supplier_disabled(self):
|
def test_supplier_disabled(self):
|
||||||
make_test_records("Item")
|
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):
|
def test_supplier_country(self):
|
||||||
# Test that country field exists in Supplier DocType
|
# Test that country field exists in Supplier DocType
|
||||||
supplier = frappe.get_doc('Supplier', '_Test Supplier with Country')
|
supplier = frappe.get_doc('Supplier', '_Test Supplier with Country')
|
||||||
self.assertTrue('country' in supplier.as_dict())
|
self.assertTrue('country' in supplier.as_dict())
|
||||||
|
|
||||||
# Test if test supplier field record is 'Greece'
|
# Test if test supplier field record is 'Greece'
|
||||||
self.assertEqual(supplier.country, "Greece")
|
self.assertEqual(supplier.country, "Greece")
|
||||||
|
|
||||||
# Test update Supplier instance country value
|
# Test update Supplier instance country value
|
||||||
supplier = frappe.get_doc('Supplier', '_Test Supplier')
|
supplier = frappe.get_doc('Supplier', '_Test Supplier')
|
||||||
supplier.country = 'Greece'
|
supplier.country = 'Greece'
|
||||||
supplier.save()
|
supplier.save()
|
||||||
self.assertEqual(supplier.country, "Greece")
|
self.assertEqual(supplier.country, "Greece")
|
||||||
|
|
||||||
def test_party_details_tax_category(self):
|
def test_party_details_tax_category(self):
|
||||||
from erpnext.accounts.party import get_party_details
|
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
|
# Tax Category without Address
|
||||||
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
|
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
|
||||||
self.assertEqual(details.tax_category, "_Test Tax Category 1")
|
self.assertEqual(details.tax_category, "_Test Tax Category 1")
|
||||||
|
|
||||||
address = frappe.get_doc(dict(
|
address = frappe.get_doc(dict(
|
||||||
doctype='Address',
|
doctype='Address',
|
||||||
address_title='_Test Address With Tax Category',
|
address_title='_Test Address With Tax Category',
|
||||||
tax_category='_Test Tax Category 2',
|
tax_category='_Test Tax Category 2',
|
||||||
address_type='Billing',
|
address_type='Billing',
|
||||||
address_line1='Station Road',
|
address_line1='Station Road',
|
||||||
city='_Test City',
|
city='_Test City',
|
||||||
country='India',
|
country='India',
|
||||||
links=[dict(
|
links=[dict(
|
||||||
link_doctype='Supplier',
|
link_doctype='Supplier',
|
||||||
link_name='_Test Supplier With Tax Category'
|
link_name='_Test Supplier With Tax Category'
|
||||||
)]
|
)]
|
||||||
)).insert()
|
)).insert()
|
||||||
|
|
||||||
# Tax Category with Address
|
# Tax Category with Address
|
||||||
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
|
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
|
||||||
self.assertEqual(details.tax_category, "_Test Tax Category 2")
|
self.assertEqual(details.tax_category, "_Test Tax Category 2")
|
||||||
|
|
||||||
# Rollback
|
# Rollback
|
||||||
address.delete()
|
address.delete()
|
||||||
|
|
||||||
def create_supplier(**args):
|
def create_supplier(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|
||||||
try:
|
if frappe.db.exists("Supplier", args.supplier_name):
|
||||||
doc = frappe.get_doc({
|
return frappe.get_doc("Supplier", args.supplier_name)
|
||||||
"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()
|
|
||||||
|
|
||||||
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 doc
|
||||||
return frappe.get_doc("Supplier", args.supplier_name)
|
|
||||||
|
@ -1566,13 +1566,12 @@ def validate_taxes_and_charges(tax):
|
|||||||
tax.rate = None
|
tax.rate = None
|
||||||
|
|
||||||
|
|
||||||
def validate_account_head(tax, doc):
|
def validate_account_head(idx, account, company):
|
||||||
company = frappe.get_cached_value('Account',
|
account_company = frappe.get_cached_value('Account', account, 'company')
|
||||||
tax.account_head, 'company')
|
|
||||||
|
|
||||||
if company != doc.company:
|
if account_company != company:
|
||||||
frappe.throw(_('Row {0}: Account {1} does not belong to Company {2}')
|
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):
|
def validate_cost_center(tax, doc):
|
||||||
|
@ -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'
|
|
||||||
}
|
|
@ -264,7 +264,7 @@ class ProductQuery:
|
|||||||
customer = get_customer(silent=True)
|
customer = get_customer(silent=True)
|
||||||
if customer:
|
if customer:
|
||||||
quotation = frappe.get_all("Quotation", fields=["name"], filters=
|
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)
|
order_by="modified desc", limit_page_length=1)
|
||||||
if quotation:
|
if quotation:
|
||||||
items = frappe.get_all(
|
items = frappe.get_all(
|
||||||
@ -298,4 +298,4 @@ class ProductQuery:
|
|||||||
# slice results manually
|
# slice results manually
|
||||||
result[:self.page_length]
|
result[:self.page_length]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -310,7 +310,7 @@ def _get_cart_quotation(party=None):
|
|||||||
party = get_party()
|
party = get_party()
|
||||||
|
|
||||||
quotation = frappe.get_all("Quotation", fields=["name"], filters=
|
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)
|
order_by="modified desc", limit_page_length=1)
|
||||||
|
|
||||||
if quotation:
|
if quotation:
|
||||||
|
@ -57,13 +57,19 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
return quotation
|
return quotation
|
||||||
|
|
||||||
def test_get_cart_customer(self):
|
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
|
self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer")
|
||||||
quotation = _get_cart_quotation()
|
validate_quotation()
|
||||||
self.assertEqual(quotation.quotation_to, "Customer")
|
|
||||||
self.assertEqual(quotation.party_name, "_Test Customer")
|
self.login_as_customer()
|
||||||
self.assertEqual(quotation.contact_email, frappe.session.user)
|
quotation = validate_quotation()
|
||||||
|
|
||||||
return quotation
|
return quotation
|
||||||
|
|
||||||
@ -175,7 +181,7 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
def create_tax_rule(self):
|
def create_tax_rule(self):
|
||||||
tax_rule = frappe.get_test_records("Tax Rule")[0]
|
tax_rule = frappe.get_test_records("Tax Rule")[0]
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(tax_rule).insert()
|
frappe.get_doc(tax_rule).insert(ignore_if_duplicate=True)
|
||||||
except (frappe.DuplicateEntryError, ConflictingTaxRule):
|
except (frappe.DuplicateEntryError, ConflictingTaxRule):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -254,10 +260,9 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.create_user_if_not_exists("test_cart_user@example.com")
|
self.create_user_if_not_exists("test_cart_user@example.com")
|
||||||
frappe.set_user("test_cart_user@example.com")
|
frappe.set_user("test_cart_user@example.com")
|
||||||
|
|
||||||
def login_as_customer(self):
|
def login_as_customer(self, email="test_contact_customer@example.com", name="_Test Contact For _Test Customer"):
|
||||||
self.create_user_if_not_exists("test_contact_customer@example.com",
|
self.create_user_if_not_exists(email, name)
|
||||||
"_Test Contact For _Test Customer")
|
frappe.set_user(email)
|
||||||
frappe.set_user("test_contact_customer@example.com")
|
|
||||||
|
|
||||||
def clear_existing_quotations(self):
|
def clear_existing_quotations(self):
|
||||||
quotations = frappe.get_all("Quotation", filters={
|
quotations = frappe.get_all("Quotation", filters={
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
frappe.provide("education");
|
frappe.provide("education");
|
||||||
|
|
||||||
frappe.ui.form.on('Student Attendance Tool', {
|
frappe.ui.form.on('Student Attendance Tool', {
|
||||||
|
setup: (frm) => {
|
||||||
|
frm.students_area = $('<div>')
|
||||||
|
.appendTo(frm.fields_dict.students_html.wrapper);
|
||||||
|
},
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query("student_group", function() {
|
frm.set_query("student_group", function() {
|
||||||
return {
|
return {
|
||||||
@ -34,6 +38,7 @@ frappe.ui.form.on('Student Attendance Tool', {
|
|||||||
|
|
||||||
student_group: function(frm) {
|
student_group: function(frm) {
|
||||||
if ((frm.doc.student_group && frm.doc.date) || frm.doc.course_schedule) {
|
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";
|
var method = "erpnext.education.doctype.student_attendance_tool.student_attendance_tool.get_student_attendance_records";
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
@ -62,10 +67,6 @@ frappe.ui.form.on('Student Attendance Tool', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get_students: function(frm, students) {
|
get_students: function(frm, students) {
|
||||||
if (!frm.students_area) {
|
|
||||||
frm.students_area = $('<div>')
|
|
||||||
.appendTo(frm.fields_dict.students_html.wrapper);
|
|
||||||
}
|
|
||||||
students = students || [];
|
students = students || [];
|
||||||
frm.students_editor = new education.StudentsEditor(frm, frm.students_area, students);
|
frm.students_editor = new education.StudentsEditor(frm, frm.students_area, students);
|
||||||
}
|
}
|
||||||
@ -163,16 +164,26 @@ education.StudentsEditor = class StudentsEditor {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
var htmls = students.map(function(student) {
|
// make html grid of students
|
||||||
return frappe.render_template("student_button", {
|
let student_html = '';
|
||||||
student: student.student,
|
for (let student of students) {
|
||||||
student_name: student.student_name,
|
student_html += `<div class="col-sm-3">
|
||||||
group_roll_number: student.group_roll_number,
|
<div class="checkbox">
|
||||||
status: student.status
|
<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() {
|
show_empty_state() {
|
||||||
|
@ -24,24 +24,24 @@ def get_student_attendance_records(based_on, date=None, student_group=None, cour
|
|||||||
student_list = frappe.get_all("Student Group Student", fields=["student", "student_name", "group_roll_number"],
|
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")
|
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:
|
if course_schedule:
|
||||||
student_attendance_list = (
|
student_attendance_list = (
|
||||||
frappe.qb.from_(table)
|
frappe.qb.from_(StudentAttendance)
|
||||||
.select(table.student, table.status)
|
.select(StudentAttendance.student, StudentAttendance.status)
|
||||||
.where(
|
.where(
|
||||||
(table.course_schedule == course_schedule)
|
(StudentAttendance.course_schedule == course_schedule)
|
||||||
)
|
)
|
||||||
).run(as_dict=True)
|
).run(as_dict=True)
|
||||||
else:
|
else:
|
||||||
student_attendance_list = (
|
student_attendance_list = (
|
||||||
frappe.qb.from_(table)
|
frappe.qb.from_(StudentAttendance)
|
||||||
.select(table.student, table.status)
|
.select(StudentAttendance.student, StudentAttendance.status)
|
||||||
.where(
|
.where(
|
||||||
(table.student_group == student_group)
|
(StudentAttendance.student_group == student_group)
|
||||||
& (table.date == date)
|
& (StudentAttendance.date == date)
|
||||||
& (table.course_schedule == "") | (table.course_schedule.isnull())
|
& ((StudentAttendance.course_schedule == "") | (StudentAttendance.course_schedule.isnull()))
|
||||||
)
|
)
|
||||||
).run(as_dict=True)
|
).run(as_dict=True)
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ class TallyMigration(Document):
|
|||||||
"is_private": True
|
"is_private": True
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
f.insert()
|
f.insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
setattr(self, key, f.file_url)
|
setattr(self, key, f.file_url)
|
||||||
|
@ -8,10 +8,6 @@ from frappe.utils import cint, flt
|
|||||||
|
|
||||||
from erpnext import get_default_company, get_region
|
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",
|
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",
|
"FR", "GB", "GR", "HR", "HU", "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PL", "PT", "RO",
|
||||||
"SE", "SI", "SK", "US"]
|
"SE", "SI", "SK", "US"]
|
||||||
@ -35,12 +31,14 @@ def get_client():
|
|||||||
if api_key and api_url:
|
if api_key and api_url:
|
||||||
client = taxjar.Client(api_key=api_key, api_url=api_url)
|
client = taxjar.Client(api_key=api_key, api_url=api_url)
|
||||||
client.set_api_config('headers', {
|
client.set_api_config('headers', {
|
||||||
'x-api-version': '2020-08-07'
|
'x-api-version': '2022-01-24'
|
||||||
})
|
})
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
|
||||||
def create_transaction(doc, method):
|
def create_transaction(doc, method):
|
||||||
|
TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
|
||||||
|
|
||||||
"""Create an order transaction in TaxJar"""
|
"""Create an order transaction in TaxJar"""
|
||||||
|
|
||||||
if not TAXJAR_CREATE_TRANSACTIONS:
|
if not TAXJAR_CREATE_TRANSACTIONS:
|
||||||
@ -51,6 +49,7 @@ def create_transaction(doc, method):
|
|||||||
if not client:
|
if not client:
|
||||||
return
|
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])
|
sales_tax = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == TAX_ACCOUNT_HEAD])
|
||||||
|
|
||||||
if not sales_tax:
|
if not sales_tax:
|
||||||
@ -79,6 +78,7 @@ def create_transaction(doc, method):
|
|||||||
|
|
||||||
def delete_transaction(doc, method):
|
def delete_transaction(doc, method):
|
||||||
"""Delete an existing TaxJar order transaction"""
|
"""Delete an existing TaxJar order transaction"""
|
||||||
|
TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
|
||||||
|
|
||||||
if not TAXJAR_CREATE_TRANSACTIONS:
|
if not TAXJAR_CREATE_TRANSACTIONS:
|
||||||
return
|
return
|
||||||
@ -92,6 +92,8 @@ def delete_transaction(doc, method):
|
|||||||
|
|
||||||
|
|
||||||
def get_tax_data(doc):
|
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_address = get_company_address_details(doc)
|
||||||
from_shipping_state = from_address.get("state")
|
from_shipping_state = from_address.get("state")
|
||||||
from_country_code = frappe.db.get_value("Country", from_address.country, "code")
|
from_country_code = frappe.db.get_value("Country", from_address.country, "code")
|
||||||
@ -113,20 +115,20 @@ def get_tax_data(doc):
|
|||||||
to_shipping_state = get_state_code(to_address, 'Shipping')
|
to_shipping_state = get_state_code(to_address, 'Shipping')
|
||||||
|
|
||||||
tax_dict = {
|
tax_dict = {
|
||||||
'from_country': from_country_code,
|
"from_country": from_country_code,
|
||||||
'from_zip': from_address.pincode,
|
"from_zip": from_address.pincode,
|
||||||
'from_state': from_shipping_state,
|
"from_state": from_shipping_state,
|
||||||
'from_city': from_address.city,
|
"from_city": from_address.city,
|
||||||
'from_street': from_address.address_line1,
|
"from_street": from_address.address_line1,
|
||||||
'to_country': to_country_code,
|
"to_country": to_country_code,
|
||||||
'to_zip': to_address.pincode,
|
"to_zip": to_address.pincode,
|
||||||
'to_city': to_address.city,
|
"to_city": to_address.city,
|
||||||
'to_street': to_address.address_line1,
|
"to_street": to_address.address_line1,
|
||||||
'to_state': to_shipping_state,
|
"to_state": to_shipping_state,
|
||||||
'shipping': shipping,
|
"shipping": shipping,
|
||||||
'amount': doc.net_total,
|
"amount": doc.net_total,
|
||||||
'plugin': 'erpnext',
|
"plugin": "erpnext",
|
||||||
'line_items': line_items
|
"line_items": line_items
|
||||||
}
|
}
|
||||||
return tax_dict
|
return tax_dict
|
||||||
|
|
||||||
@ -156,6 +158,9 @@ def get_line_item_dict(item, docstatus):
|
|||||||
return tax_dict
|
return tax_dict
|
||||||
|
|
||||||
def set_sales_tax(doc, method):
|
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:
|
if not TAXJAR_CALCULATE_TAX:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -206,6 +211,7 @@ def set_sales_tax(doc, method):
|
|||||||
doc.run_method("calculate_taxes_and_totals")
|
doc.run_method("calculate_taxes_and_totals")
|
||||||
|
|
||||||
def check_for_nexus(doc, tax_dict):
|
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"]}):
|
if not frappe.db.get_value('TaxJar Nexus', {'region_code': tax_dict["to_state"]}):
|
||||||
for item in doc.get("items"):
|
for item in doc.get("items"):
|
||||||
item.tax_collectable = flt(0)
|
item.tax_collectable = flt(0)
|
||||||
@ -218,6 +224,8 @@ def check_for_nexus(doc, tax_dict):
|
|||||||
|
|
||||||
def check_sales_tax_exemption(doc):
|
def check_sales_tax_exemption(doc):
|
||||||
# if the party is exempt from sales tax, then set all tax account heads to zero
|
# 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 \
|
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") \
|
or frappe.db.has_column("Customer", "exempt_from_sales_tax") \
|
||||||
and frappe.db.get_value("Customer", doc.customer, "exempt_from_sales_tax")
|
and frappe.db.get_value("Customer", doc.customer, "exempt_from_sales_tax")
|
||||||
|
@ -68,7 +68,6 @@ domains = {
|
|||||||
'Distribution': 'erpnext.domains.distribution',
|
'Distribution': 'erpnext.domains.distribution',
|
||||||
'Education': 'erpnext.domains.education',
|
'Education': 'erpnext.domains.education',
|
||||||
'Manufacturing': 'erpnext.domains.manufacturing',
|
'Manufacturing': 'erpnext.domains.manufacturing',
|
||||||
'Non Profit': 'erpnext.domains.non_profit',
|
|
||||||
'Retail': 'erpnext.domains.retail',
|
'Retail': 'erpnext.domains.retail',
|
||||||
'Services': 'erpnext.domains.services',
|
'Services': 'erpnext.domains.services',
|
||||||
}
|
}
|
||||||
@ -175,7 +174,6 @@ standard_portal_menu_items = [
|
|||||||
{"title": _("Fees"), "route": "/fees", "reference_doctype": "Fees", "role":"Student"},
|
{"title": _("Fees"), "route": "/fees", "reference_doctype": "Fees", "role":"Student"},
|
||||||
{"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"},
|
{"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"},
|
||||||
{"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission", "role": "Student"},
|
{"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": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"},
|
||||||
{"title": _("Appointment Booking"), "route": "/book_appointment"},
|
{"title": _("Appointment Booking"), "route": "/book_appointment"},
|
||||||
]
|
]
|
||||||
@ -369,7 +367,6 @@ scheduler_events = {
|
|||||||
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
|
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
|
||||||
"erpnext.buying.doctype.supplier_quotation.supplier_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.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"
|
"erpnext.hr.doctype.interview.interview.send_daily_feedback_reminder"
|
||||||
],
|
],
|
||||||
"daily_long": [
|
"daily_long": [
|
||||||
@ -563,19 +560,6 @@ global_search_doctypes = {
|
|||||||
{'doctype': 'Assessment Code', 'index': 39},
|
{'doctype': 'Assessment Code', 'index': 39},
|
||||||
{'doctype': 'Discussion', 'index': 40},
|
{'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 = {
|
additional_timeline_content = {
|
||||||
|
@ -32,7 +32,7 @@ class Department(NestedSet):
|
|||||||
return new
|
return new
|
||||||
|
|
||||||
def on_update(self):
|
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()
|
super(Department, self).on_update()
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[
|
[
|
||||||
{"doctype":"Department", "department_name":"_Test Department", "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"}
|
{"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company", "parent_department": "All Departments"}
|
||||||
]
|
]
|
@ -142,7 +142,7 @@ class Employee(NestedSet):
|
|||||||
"file_url": self.image,
|
"file_url": self.image,
|
||||||
"attached_to_doctype": "User",
|
"attached_to_doctype": "User",
|
||||||
"attached_to_name": self.user_id
|
"attached_to_name": self.user_id
|
||||||
}).insert()
|
}).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
# already exists
|
# already exists
|
||||||
pass
|
pass
|
||||||
|
@ -128,4 +128,4 @@ def show_email_summary(email_success, email_failure):
|
|||||||
message += _('{0} due to missing email information for employee(s): {1}').format(
|
message += _('{0} due to missing email information for employee(s): {1}').format(
|
||||||
frappe.bold('Sending Failed'), ', '.join(email_failure))
|
frappe.bold('Sending Failed'), ', '.join(email_failure))
|
||||||
|
|
||||||
frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True)
|
frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True)
|
||||||
|
@ -82,7 +82,7 @@ def get_vehicle(employee_id):
|
|||||||
"vehicle_value": flt(500000)
|
"vehicle_value": flt(500000)
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
vehicle.insert()
|
vehicle.insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
return license_plate
|
return license_plate
|
||||||
|
@ -14,11 +14,15 @@
|
|||||||
"applicant",
|
"applicant",
|
||||||
"section_break_7",
|
"section_break_7",
|
||||||
"disbursement_date",
|
"disbursement_date",
|
||||||
|
"clearance_date",
|
||||||
"column_break_8",
|
"column_break_8",
|
||||||
"disbursed_amount",
|
"disbursed_amount",
|
||||||
"accounting_dimensions_section",
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
"customer_details_section",
|
"accounting_details",
|
||||||
|
"disbursement_account",
|
||||||
|
"column_break_16",
|
||||||
|
"loan_account",
|
||||||
"bank_account",
|
"bank_account",
|
||||||
"disbursement_references_section",
|
"disbursement_references_section",
|
||||||
"reference_date",
|
"reference_date",
|
||||||
@ -106,11 +110,6 @@
|
|||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Disbursement Details"
|
"label": "Disbursement Details"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "customer_details_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Customer Details"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fetch_from": "against_loan.applicant_type",
|
"fetch_from": "against_loan.applicant_type",
|
||||||
"fieldname": "applicant_type",
|
"fieldname": "applicant_type",
|
||||||
@ -149,15 +148,48 @@
|
|||||||
"fieldname": "reference_number",
|
"fieldname": "reference_number",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Reference Number"
|
"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,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-04-19 18:09:32.175355",
|
"modified": "2022-02-17 18:23:44.157598",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Disbursement",
|
"name": "Loan Disbursement",
|
||||||
|
"naming_rule": "Expression (old style)",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -194,5 +226,6 @@
|
|||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -42,9 +42,6 @@ class LoanDisbursement(AccountsController):
|
|||||||
if not self.posting_date:
|
if not self.posting_date:
|
||||||
self.posting_date = self.disbursement_date or nowdate()
|
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):
|
def validate_disbursal_amount(self):
|
||||||
possible_disbursal_amount = get_disbursal_amount(self.against_loan)
|
possible_disbursal_amount = get_disbursal_amount(self.against_loan)
|
||||||
|
|
||||||
@ -117,12 +114,11 @@ class LoanDisbursement(AccountsController):
|
|||||||
|
|
||||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||||
gle_map = []
|
gle_map = []
|
||||||
loan_details = frappe.get_doc("Loan", self.against_loan)
|
|
||||||
|
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.loan_account,
|
"account": self.loan_account,
|
||||||
"against": loan_details.disbursement_account,
|
"against": self.disbursement_account,
|
||||||
"debit": self.disbursed_amount,
|
"debit": self.disbursed_amount,
|
||||||
"debit_in_account_currency": self.disbursed_amount,
|
"debit_in_account_currency": self.disbursed_amount,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
@ -137,8 +133,8 @@ class LoanDisbursement(AccountsController):
|
|||||||
|
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.disbursement_account,
|
"account": self.disbursement_account,
|
||||||
"against": loan_details.loan_account,
|
"against": self.loan_account,
|
||||||
"credit": self.disbursed_amount,
|
"credit": self.disbursed_amount,
|
||||||
"credit_in_account_currency": self.disbursed_amount,
|
"credit_in_account_currency": self.disbursed_amount,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"autoname": "LM-REP-.####",
|
"autoname": "LM-REP-.####",
|
||||||
"creation": "2019-09-03 14:44:39.977266",
|
"creation": "2022-01-25 10:30:02.767941",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
@ -13,6 +13,7 @@
|
|||||||
"column_break_3",
|
"column_break_3",
|
||||||
"company",
|
"company",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
|
"clearance_date",
|
||||||
"rate_of_interest",
|
"rate_of_interest",
|
||||||
"payroll_payable_account",
|
"payroll_payable_account",
|
||||||
"is_term_loan",
|
"is_term_loan",
|
||||||
@ -37,7 +38,12 @@
|
|||||||
"total_penalty_paid",
|
"total_penalty_paid",
|
||||||
"total_interest_paid",
|
"total_interest_paid",
|
||||||
"repayment_details",
|
"repayment_details",
|
||||||
"amended_from"
|
"amended_from",
|
||||||
|
"accounting_details_section",
|
||||||
|
"payment_account",
|
||||||
|
"penalty_income_account",
|
||||||
|
"column_break_36",
|
||||||
|
"loan_account"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -260,12 +266,52 @@
|
|||||||
"fieldname": "repay_from_salary",
|
"fieldname": "repay_from_salary",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Repay From Salary"
|
"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,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-01-06 01:51:06.707782",
|
"modified": "2022-02-18 19:10:07.742298",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Repayment",
|
"name": "Loan Repayment",
|
||||||
|
@ -310,7 +310,6 @@ class LoanRepayment(AccountsController):
|
|||||||
|
|
||||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||||
gle_map = []
|
gle_map = []
|
||||||
loan_details = frappe.get_doc("Loan", self.against_loan)
|
|
||||||
|
|
||||||
if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
|
if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
|
||||||
remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(self.shortfall_amount,
|
remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(self.shortfall_amount,
|
||||||
@ -323,13 +322,13 @@ class LoanRepayment(AccountsController):
|
|||||||
if self.repay_from_salary:
|
if self.repay_from_salary:
|
||||||
payment_account = self.payroll_payable_account
|
payment_account = self.payroll_payable_account
|
||||||
else:
|
else:
|
||||||
payment_account = loan_details.payment_account
|
payment_account = self.payment_account
|
||||||
|
|
||||||
if self.total_penalty_paid:
|
if self.total_penalty_paid:
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.loan_account,
|
"account": self.loan_account,
|
||||||
"against": loan_details.payment_account,
|
"against": payment_account,
|
||||||
"debit": self.total_penalty_paid,
|
"debit": self.total_penalty_paid,
|
||||||
"debit_in_account_currency": self.total_penalty_paid,
|
"debit_in_account_currency": self.total_penalty_paid,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
@ -344,8 +343,8 @@ class LoanRepayment(AccountsController):
|
|||||||
|
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.penalty_income_account,
|
"account": self.penalty_income_account,
|
||||||
"against": loan_details.loan_account,
|
"against": self.loan_account,
|
||||||
"credit": self.total_penalty_paid,
|
"credit": self.total_penalty_paid,
|
||||||
"credit_in_account_currency": self.total_penalty_paid,
|
"credit_in_account_currency": self.total_penalty_paid,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
@ -359,8 +358,7 @@ class LoanRepayment(AccountsController):
|
|||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": payment_account,
|
"account": payment_account,
|
||||||
"against": loan_details.loan_account + ", " + loan_details.interest_income_account
|
"against": self.loan_account + ", " + self.penalty_income_account,
|
||||||
+ ", " + loan_details.penalty_income_account,
|
|
||||||
"debit": self.amount_paid,
|
"debit": self.amount_paid,
|
||||||
"debit_in_account_currency": self.amount_paid,
|
"debit_in_account_currency": self.amount_paid,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
@ -368,16 +366,16 @@ class LoanRepayment(AccountsController):
|
|||||||
"remarks": remarks,
|
"remarks": remarks,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
"posting_date": getdate(self.posting_date),
|
"posting_date": getdate(self.posting_date),
|
||||||
"party_type": loan_details.applicant_type if self.repay_from_salary else '',
|
"party_type": self.applicant_type if self.repay_from_salary else '',
|
||||||
"party": loan_details.applicant if self.repay_from_salary else ''
|
"party": self.applicant if self.repay_from_salary else ''
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.loan_account,
|
"account": self.loan_account,
|
||||||
"party_type": loan_details.applicant_type,
|
"party_type": self.applicant_type,
|
||||||
"party": loan_details.applicant,
|
"party": self.applicant,
|
||||||
"against": payment_account,
|
"against": payment_account,
|
||||||
"credit": self.amount_paid,
|
"credit": self.amount_paid,
|
||||||
"credit_in_account_currency": self.amount_paid,
|
"credit_in_account_currency": self.amount_paid,
|
||||||
|
@ -9,6 +9,7 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import (
|
|||||||
get_sales_orders,
|
get_sales_orders,
|
||||||
get_warehouse_list,
|
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.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.item.test_item import create_item
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
@ -466,26 +467,29 @@ class TestProductionPlan(ERPNextTestCase):
|
|||||||
bom = make_bom(item=item, raw_materials=raw_materials)
|
bom = make_bom(item=item, raw_materials=raw_materials)
|
||||||
|
|
||||||
# Create Production Plan
|
# 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
|
# All the created Work Orders
|
||||||
wo_list = []
|
wo_list = []
|
||||||
|
|
||||||
# Create and Submit 1st Work Order for 5 qty
|
# Create and Submit 1st Work Order for 3 qty
|
||||||
create_work_order(item, pln, 5)
|
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()
|
pln.reload()
|
||||||
self.assertEqual(pln.po_items[0].ordered_qty, 5)
|
self.assertEqual(pln.po_items[0].ordered_qty, 5)
|
||||||
|
|
||||||
# Create and Submit 2nd Work Order for 3 qty
|
# Overproduction
|
||||||
create_work_order(item, pln, 3)
|
self.assertRaises(OverProductionError, create_work_order, item=item, pln=pln, qty=2)
|
||||||
pln.reload()
|
|
||||||
self.assertEqual(pln.po_items[0].ordered_qty, 8)
|
|
||||||
|
|
||||||
# Cancel 1st Work Order
|
# Cancel 1st Work Order
|
||||||
wo1 = frappe.get_doc("Work Order", wo_list[0])
|
wo1 = frappe.get_doc("Work Order", wo_list[0])
|
||||||
wo1.cancel()
|
wo1.cancel()
|
||||||
pln.reload()
|
pln.reload()
|
||||||
self.assertEqual(pln.po_items[0].ordered_qty, 3)
|
self.assertEqual(pln.po_items[0].ordered_qty, 2)
|
||||||
|
|
||||||
# Cancel 2nd Work Order
|
# Cancel 2nd Work Order
|
||||||
wo2 = frappe.get_doc("Work Order", wo_list[1])
|
wo2 = frappe.get_doc("Work Order", wo_list[1])
|
||||||
|
@ -636,6 +636,21 @@ class WorkOrder(Document):
|
|||||||
if not self.qty > 0:
|
if not self.qty > 0:
|
||||||
frappe.throw(_("Quantity to Manufacture must be greater than 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):
|
def validate_transfer_against(self):
|
||||||
if not self.docstatus == 1:
|
if not self.docstatus == 1:
|
||||||
# let user configure operations until they're ready to submit
|
# let user configure operations until they're ready to submit
|
||||||
|
@ -55,10 +55,11 @@ class TestManufacturingReports(unittest.TestCase):
|
|||||||
def test_execute_all_manufacturing_reports(self):
|
def test_execute_all_manufacturing_reports(self):
|
||||||
"""Test that all script report in manufacturing modules are executable with supported filters"""
|
"""Test that all script report in manufacturing modules are executable with supported filters"""
|
||||||
for report, filter in REPORT_FILTER_TEST_CASES:
|
for report, filter in REPORT_FILTER_TEST_CASES:
|
||||||
execute_script_report(
|
with self.subTest(report=report):
|
||||||
report_name=report,
|
execute_script_report(
|
||||||
module="Manufacturing",
|
report_name=report,
|
||||||
filters=filter,
|
module="Manufacturing",
|
||||||
default_filters=DEFAULT_FILTERS,
|
filters=filter,
|
||||||
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
default_filters=DEFAULT_FILTERS,
|
||||||
)
|
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
||||||
|
)
|
||||||
|
@ -15,7 +15,6 @@ Maintenance
|
|||||||
Education
|
Education
|
||||||
Regional
|
Regional
|
||||||
ERPNext Integrations
|
ERPNext Integrations
|
||||||
Non Profit
|
|
||||||
Quality Management
|
Quality Management
|
||||||
Communication
|
Communication
|
||||||
Loan Management
|
Loan Management
|
||||||
|
@ -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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestCertificationApplication(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestCertifiedConsultant(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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"
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestChapter(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -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']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -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()
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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)
|
|
@ -1,3 +0,0 @@
|
|||||||
frappe.listview_settings['Donor'] = {
|
|
||||||
add_fields: ["donor_name", "donor_type", "image"],
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestDonor(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestDonorType(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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"))
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestGrantApplication(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -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']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
frappe.listview_settings['Member'] = {
|
|
||||||
add_fields: ["member_name", "membership_type", "image"],
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestMember(unittest.TestCase):
|
|
||||||
pass
|
|
@ -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");
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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()))
|
|
@ -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'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -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"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user