diff --git a/erpnext/__init__.py b/erpnext/__init__.py index bef6661254..dcfad1f100 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -131,11 +131,3 @@ def allow_regional(fn): return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs) return caller - -def get_last_membership(member): - '''Returns last membership if exists''' - last_membership = frappe.get_all('Membership', 'name,to_date,membership_type', - dict(member=member, paid=1), order_by='to_date desc', limit=1) - - if last_membership: - return last_membership[0] diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 4211bd0169..f3351ddcba 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -7,6 +7,7 @@ import json import frappe from frappe import _ from frappe.model.document import Document +from frappe.query_builder.custom import ConstantColumn from frappe.utils import flt from erpnext import get_company_currency @@ -275,6 +276,10 @@ def check_matching(bank_account, company, transaction, document_types): } matching_vouchers = [] + + matching_vouchers.extend(get_loan_vouchers(bank_account, transaction, + document_types, filters)) + for query in subquery: matching_vouchers.extend( frappe.db.sql(query, filters,) @@ -311,6 +316,114 @@ def get_queries(bank_account, company, transaction, document_types): return queries +def get_loan_vouchers(bank_account, transaction, document_types, filters): + vouchers = [] + amount_condition = True if "exact_match" in document_types else False + + if transaction.withdrawal > 0 and "loan_disbursement" in document_types: + vouchers.extend(get_ld_matching_query(bank_account, amount_condition, filters)) + + if transaction.deposit > 0 and "loan_repayment" in document_types: + vouchers.extend(get_lr_matching_query(bank_account, amount_condition, filters)) + + return vouchers + +def get_ld_matching_query(bank_account, amount_condition, filters): + loan_disbursement = frappe.qb.DocType("Loan Disbursement") + matching_reference = loan_disbursement.reference_number == filters.get("reference_number") + matching_party = loan_disbursement.applicant_type == filters.get("party_type") and \ + loan_disbursement.applicant == filters.get("party") + + rank = ( + frappe.qb.terms.Case() + .when(matching_reference, 1) + .else_(0) + ) + + rank1 = ( + frappe.qb.terms.Case() + .when(matching_party, 1) + .else_(0) + ) + + query = frappe.qb.from_(loan_disbursement).select( + rank + rank1 + 1, + ConstantColumn("Loan Disbursement").as_("doctype"), + loan_disbursement.name, + loan_disbursement.disbursed_amount, + loan_disbursement.reference_number, + loan_disbursement.reference_date, + loan_disbursement.applicant_type, + loan_disbursement.disbursement_date + ).where( + loan_disbursement.docstatus == 1 + ).where( + loan_disbursement.clearance_date.isnull() + ).where( + loan_disbursement.disbursement_account == bank_account + ) + + if amount_condition: + query.where( + loan_disbursement.disbursed_amount == filters.get('amount') + ) + else: + query.where( + loan_disbursement.disbursed_amount <= filters.get('amount') + ) + + vouchers = query.run(as_list=True) + + return vouchers + +def get_lr_matching_query(bank_account, amount_condition, filters): + loan_repayment = frappe.qb.DocType("Loan Repayment") + matching_reference = loan_repayment.reference_number == filters.get("reference_number") + matching_party = loan_repayment.applicant_type == filters.get("party_type") and \ + loan_repayment.applicant == filters.get("party") + + rank = ( + frappe.qb.terms.Case() + .when(matching_reference, 1) + .else_(0) + ) + + rank1 = ( + frappe.qb.terms.Case() + .when(matching_party, 1) + .else_(0) + ) + + query = frappe.qb.from_(loan_repayment).select( + rank + rank1 + 1, + ConstantColumn("Loan Repayment").as_("doctype"), + loan_repayment.name, + loan_repayment.amount_paid, + loan_repayment.reference_number, + loan_repayment.reference_date, + loan_repayment.applicant_type, + loan_repayment.posting_date + ).where( + loan_repayment.docstatus == 1 + ).where( + loan_repayment.clearance_date.isnull() + ).where( + loan_repayment.payment_account == bank_account + ) + + if amount_condition: + query.where( + loan_repayment.amount_paid == filters.get('amount') + ) + else: + query.where( + loan_repayment.amount_paid <= filters.get('amount') + ) + + vouchers = query.run() + + return vouchers + def get_pe_matching_query(amount_condition, account_from_to, transaction): # get matching payment entries query if transaction.deposit > 0: @@ -348,7 +461,6 @@ def get_je_matching_query(amount_condition, transaction): # We have mapping at the bank level # So one bank could have both types of bank accounts like asset and liability # So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type - company_account = frappe.get_value("Bank Account", transaction.bank_account, "account") cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit" return f""" diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 51e1d6e9a0..a476cab55f 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -49,7 +49,8 @@ class BankTransaction(StatusUpdater): def clear_linked_payment_entries(self, for_cancel=False): for payment_entry in self.payment_entries: - if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]: + if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim", "Loan Repayment", + "Loan Disbursement"]: self.clear_simple_entry(payment_entry, for_cancel=for_cancel) elif payment_entry.payment_document == "Sales Invoice": @@ -116,11 +117,18 @@ def get_paid_amount(payment_entry, currency, bank_account): payment_entry.payment_entry, paid_amount_field) elif payment_entry.payment_document == "Journal Entry": - return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, "sum(credit_in_account_currency)") + return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, + "sum(credit_in_account_currency)") elif payment_entry.payment_document == "Expense Claim": return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed") + elif payment_entry.payment_document == "Loan Disbursement": + return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "disbursed_amount") + + elif payment_entry.payment_document == "Loan Repayment": + return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid") + else: frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry)) diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py index 72b6893faf..d84b8e07d3 100644 --- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py @@ -109,7 +109,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"): frappe.get_doc({ "doctype": "Bank", "bank_name":bank_name, - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -119,7 +119,7 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"): "account_name":"Checking Account", "bank": bank_name, "account": account_name - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -184,7 +184,7 @@ def add_vouchers(): "supplier_group":"All Supplier Groups", "supplier_type": "Company", "supplier_name": "Conrad Electronic" - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -203,7 +203,7 @@ def add_vouchers(): "supplier_group":"All Supplier Groups", "supplier_type": "Company", "supplier_name": "Mr G" - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -227,7 +227,7 @@ def add_vouchers(): "supplier_group":"All Supplier Groups", "supplier_type": "Company", "supplier_name": "Poore Simon's" - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -237,7 +237,7 @@ def add_vouchers(): "customer_group":"All Customer Groups", "customer_type": "Company", "customer_name": "Poore Simon's" - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -266,7 +266,7 @@ def add_vouchers(): "customer_group":"All Customer Groups", "customer_type": "Company", "customer_name": "Fayva" - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py index ade7f8146b..6e7b80e731 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py @@ -166,7 +166,7 @@ class OpeningInvoiceCreationTool(Document): frappe.scrub(row.party_type): row.party, "is_pos": 0, "doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice", - "update_stock": 0, + "update_stock": 0, # important: https://github.com/frappe/erpnext/pull/23559 "invoice_number": row.invoice_number, "disable_rounded_total": 1 }) diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py index 6700e9b975..3eaf6a28f3 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py @@ -1,11 +1,7 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest - import frappe -from frappe.cache_manager import clear_doctype_cache -from frappe.custom.doctype.property_setter.property_setter import make_property_setter from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import ( create_dimension, @@ -14,14 +10,17 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp from erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool import ( get_temporary_opening_account, ) +from erpnext.tests.utils import ERPNextTestCase test_dependencies = ["Customer", "Supplier", "Accounting Dimension"] -class TestOpeningInvoiceCreationTool(unittest.TestCase): - def setUp(self): +class TestOpeningInvoiceCreationTool(ERPNextTestCase): + @classmethod + def setUpClass(self): if not frappe.db.exists("Company", "_Test Opening Invoice Company"): make_company() create_dimension() + return super().setUpClass() def make_invoices(self, invoice_type="Sales", company=None, party_1=None, party_2=None, invoice_number=None, department=None): doc = frappe.get_single("Opening Invoice Creation Tool") @@ -31,26 +30,20 @@ class TestOpeningInvoiceCreationTool(unittest.TestCase): return doc.make_invoices() def test_opening_sales_invoice_creation(self): - property_setter = make_property_setter("Sales Invoice", "update_stock", "default", 1, "Check") - try: - invoices = self.make_invoices(company="_Test Opening Invoice Company") + invoices = self.make_invoices(company="_Test Opening Invoice Company") - self.assertEqual(len(invoices), 2) - expected_value = { - "keys": ["customer", "outstanding_amount", "status"], - 0: ["_Test Customer", 300, "Overdue"], - 1: ["_Test Customer 1", 250, "Overdue"], - } - self.check_expected_values(invoices, expected_value) + self.assertEqual(len(invoices), 2) + expected_value = { + "keys": ["customer", "outstanding_amount", "status"], + 0: ["_Test Customer", 300, "Overdue"], + 1: ["_Test Customer 1", 250, "Overdue"], + } + self.check_expected_values(invoices, expected_value) - si = frappe.get_doc("Sales Invoice", invoices[0]) + si = frappe.get_doc("Sales Invoice", invoices[0]) - # Check if update stock is not enabled - self.assertEqual(si.update_stock, 0) - - finally: - property_setter.delete() - clear_doctype_cache("Sales Invoice") + # Check if update stock is not enabled + self.assertEqual(si.update_stock, 0) def check_expected_values(self, invoices, expected_value, invoice_type="Sales"): doctype = "Sales Invoice" if invoice_type == "Sales" else "Purchase Invoice" diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 3be3925b5a..a9bc0280bc 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -114,8 +114,6 @@ frappe.ui.form.on('Payment Entry', { var doctypes = ["Expense Claim", "Journal Entry"]; } else if (frm.doc.party_type == "Student") { var doctypes = ["Fees"]; - } else if (frm.doc.party_type == "Donor") { - var doctypes = ["Donation"]; } else { var doctypes = ["Journal Entry"]; } @@ -144,7 +142,7 @@ frappe.ui.form.on('Payment Entry', { const child = locals[cdt][cdn]; const filters = {"docstatus": 1, "company": doc.company}; const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice', - 'Purchase Order', 'Expense Claim', 'Fees', 'Dunning', 'Donation']; + 'Purchase Order', 'Expense Claim', 'Fees', 'Dunning']; if (in_list(party_type_doctypes, child.reference_doctype)) { filters[doc.party_type.toLowerCase()] = doc.party; @@ -747,8 +745,7 @@ frappe.ui.form.on('Payment Entry', { (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") || (frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") || (frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") || - (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") || - (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor") + (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ) { if(total_positive_outstanding > total_negative_outstanding) if (!frm.doc.paid_amount) @@ -791,8 +788,7 @@ frappe.ui.form.on('Payment Entry', { (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") || (frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") || (frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") || - (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") || - (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor") + (frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ) { if(total_positive_outstanding_including_order > paid_amount) { var remaining_outstanding = total_positive_outstanding_including_order - paid_amount; @@ -951,12 +947,6 @@ frappe.ui.form.on('Payment Entry', { frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx])); return false; } - - if (frm.doc.party_type == "Donor" && row.reference_doctype != "Donation") { - frappe.model.set_value(row.doctype, row.name, "reference_doctype", null); - frappe.msgprint(__("Row #{0}: Reference Document Type must be Donation", [row.idx])); - return false; - } } if (row) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 02a144d3e7..c36c843889 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -91,7 +91,6 @@ class PaymentEntry(AccountsController): self.update_expense_claim() self.update_outstanding_amounts() self.update_advance_paid() - self.update_donation() self.update_payment_schedule() self.set_status() @@ -101,7 +100,6 @@ class PaymentEntry(AccountsController): self.update_expense_claim() self.update_outstanding_amounts() self.update_advance_paid() - self.update_donation(cancel=1) self.delink_advance_entry_references() self.update_payment_schedule(cancel=1) self.set_payment_req_status() @@ -284,8 +282,6 @@ class PaymentEntry(AccountsController): valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity") elif self.party_type == "Shareholder": valid_reference_doctypes = ("Journal Entry") - elif self.party_type == "Donor": - valid_reference_doctypes = ("Donation") for d in self.get("references"): if not d.allocated_amount: @@ -843,13 +839,6 @@ class PaymentEntry(AccountsController): else: update_reimbursed_amount(doc, d.allocated_amount) - def update_donation(self, cancel=0): - if self.payment_type == "Receive" and self.party_type == "Donor" and self.party: - for d in self.get("references"): - if d.reference_doctype=="Donation" and d.reference_name: - is_paid = 0 if cancel else 1 - frappe.db.set_value("Donation", d.reference_name, "paid", is_paid) - def on_recurring(self, reference_doc, auto_repeat_doc): self.reference_no = reference_doc.name self.reference_date = nowdate() @@ -1077,7 +1066,7 @@ def get_outstanding_reference_documents(args): if d.voucher_type in ("Purchase Invoice"): d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no") - # Get all SO / PO which are not fully billed or aginst which full advance not paid + # Get all SO / PO which are not fully billed or against which full advance not paid orders_to_be_billed = [] if (args.get("party_type") != "Student"): orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), @@ -1337,10 +1326,6 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre total_amount = ref_doc.get("grand_total") exchange_rate = 1 outstanding_amount = ref_doc.get("outstanding_amount") - elif reference_doctype == "Donation": - total_amount = ref_doc.get("amount") - outstanding_amount = total_amount - exchange_rate = 1 elif reference_doctype == "Dunning": total_amount = ref_doc.get("dunning_amount") exchange_rate = 1 @@ -1611,8 +1596,6 @@ def set_party_type(dt): party_type = "Employee" elif dt == "Fees": party_type = "Student" - elif dt == "Donation": - party_type = "Donor" return party_type def set_party_account(dt, dn, doc, party_type): @@ -1640,7 +1623,7 @@ def set_party_account_currency(dt, party_account, doc): return party_account_currency def set_payment_type(dt, doc): - if (dt in ("Sales Order", "Donation") or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \ + if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \ or (dt=="Purchase Invoice" and doc.outstanding_amount < 0): payment_type = "Receive" else: @@ -1673,9 +1656,6 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre elif dt == "Dunning": grand_total = doc.grand_total outstanding_amount = doc.grand_total - elif dt == "Donation": - grand_total = doc.amount - outstanding_amount = doc.amount elif dt == "Gratuity": grand_total = doc.amount outstanding_amount = flt(doc.amount) - flt(doc.paid_amount) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 5229d87017..9b3b3aa414 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -439,7 +439,6 @@ class POSInvoice(SalesInvoice): self.paid_amount = 0 def set_account_for_mode_of_payment(self): - self.payments = [d for d in self.payments if d.amount or d.base_amount or d.default] for pay in self.payments: if not pay.account: pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account") diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py index b5909447dc..1d30934df9 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py @@ -46,7 +46,7 @@ def valdiate_taxes_and_charges_template(doc): for tax in doc.get("taxes"): validate_taxes_and_charges(tax) - validate_account_head(tax, doc) + validate_account_head(tax.idx, tax.account_head, doc.company) validate_cost_center(tax, doc) validate_inclusive_tax(tax, doc) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index c13bc23c15..d6f6c5bcb6 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -307,7 +307,7 @@ def validate_party_gle_currency(party_type, party, company, party_account_curren .format(frappe.bold(party_type), frappe.bold(party), frappe.bold(existing_gle_currency), frappe.bold(company)), InvalidAccountCurrency) def validate_party_accounts(doc): - + from erpnext.controllers.accounts_controller import validate_account_head companies = [] for account in doc.get("accounts"): @@ -330,6 +330,9 @@ def validate_party_accounts(doc): if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency: frappe.throw(_("Billing currency must be equal to either default company's currency or party account currency")) + # validate if account is mapped for same company + validate_account_head(account.idx, account.account, account.company) + @frappe.whitelist() def get_due_date(posting_date, party_type, party, company=None, bill_date=None): diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index 6c401fb8f3..b72d266977 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -4,7 +4,12 @@ import frappe from frappe import _ -from frappe.utils import flt, getdate, nowdate +from frappe.query_builder.custom import ConstantColumn +from frappe.query_builder.functions import Sum +from frappe.utils import flt, getdate +from pypika import CustomFunction + +from erpnext.accounts.utils import get_balance_on def execute(filters=None): @@ -18,7 +23,6 @@ def execute(filters=None): data = get_entries(filters) - from erpnext.accounts.utils import get_balance_on balance_as_per_system = get_balance_on(filters["account"], filters["report_date"]) total_debit, total_credit = 0,0 @@ -118,7 +122,21 @@ def get_columns(): ] def get_entries(filters): - journal_entries = frappe.db.sql(""" + journal_entries = get_journal_entries(filters) + + payment_entries = get_payment_entries(filters) + + loan_entries = get_loan_entries(filters) + + pos_entries = [] + if filters.include_pos_transactions: + pos_entries = get_pos_entries(filters) + + return sorted(list(payment_entries)+list(journal_entries+list(pos_entries) + list(loan_entries)), + key=lambda k: getdate(k['posting_date'])) + +def get_journal_entries(filters): + return frappe.db.sql(""" select "Journal Entry" as payment_document, jv.posting_date, jv.name as payment_entry, jvd.debit_in_account_currency as debit, jvd.credit_in_account_currency as credit, jvd.against_account, @@ -130,7 +148,8 @@ def get_entries(filters): and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s and ifnull(jv.is_opening, 'No') = 'No'""", filters, as_dict=1) - payment_entries = frappe.db.sql(""" +def get_payment_entries(filters): + return frappe.db.sql(""" select "Payment Entry" as payment_document, name as payment_entry, reference_no, reference_date as ref_date, @@ -145,9 +164,8 @@ def get_entries(filters): and ifnull(clearance_date, '4000-01-01') > %(report_date)s """, filters, as_dict=1) - pos_entries = [] - if filters.include_pos_transactions: - pos_entries = frappe.db.sql(""" +def get_pos_entries(filters): + return frappe.db.sql(""" select "Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit, si.posting_date, si.debit_to as against_account, sip.clearance_date, @@ -161,8 +179,42 @@ def get_entries(filters): si.posting_date ASC, si.name DESC """, filters, as_dict=1) - return sorted(list(payment_entries)+list(journal_entries+list(pos_entries)), - key=lambda k: k['posting_date'] or getdate(nowdate())) +def get_loan_entries(filters): + loan_docs = [] + for doctype in ["Loan Disbursement", "Loan Repayment"]: + loan_doc = frappe.qb.DocType(doctype) + ifnull = CustomFunction('IFNULL', ['value', 'default']) + + if doctype == "Loan Disbursement": + amount_field = (loan_doc.disbursed_amount).as_("credit") + posting_date = (loan_doc.disbursement_date).as_("posting_date") + account = loan_doc.disbursement_account + else: + amount_field = (loan_doc.amount_paid).as_("debit") + posting_date = (loan_doc.posting_date).as_("posting_date") + account = loan_doc.payment_account + + entries = frappe.qb.from_(loan_doc).select( + ConstantColumn(doctype).as_("payment_document"), + (loan_doc.name).as_("payment_entry"), + (loan_doc.reference_number).as_("reference_no"), + (loan_doc.reference_date).as_("ref_date"), + amount_field, + posting_date, + ).where( + loan_doc.docstatus == 1 + ).where( + account == filters.get('account') + ).where( + posting_date <= getdate(filters.get('report_date')) + ).where( + ifnull(loan_doc.clearance_date, '4000-01-01') > getdate(filters.get('report_date')) + ).run(as_dict=1) + + loan_docs.extend(entries) + + return loan_docs + def get_amounts_not_reflected_in_system(filters): je_amount = frappe.db.sql(""" @@ -182,7 +234,40 @@ def get_amounts_not_reflected_in_system(filters): pe_amount = flt(pe_amount[0][0]) if pe_amount else 0.0 - return je_amount + pe_amount + loan_amount = get_loan_amount(filters) + + return je_amount + pe_amount + loan_amount + +def get_loan_amount(filters): + total_amount = 0 + for doctype in ["Loan Disbursement", "Loan Repayment"]: + loan_doc = frappe.qb.DocType(doctype) + ifnull = CustomFunction('IFNULL', ['value', 'default']) + + if doctype == "Loan Disbursement": + amount_field = Sum(loan_doc.disbursed_amount) + posting_date = (loan_doc.disbursement_date).as_("posting_date") + account = loan_doc.disbursement_account + else: + amount_field = Sum(loan_doc.amount_paid) + posting_date = (loan_doc.posting_date).as_("posting_date") + account = loan_doc.payment_account + + amount = frappe.qb.from_(loan_doc).select( + amount_field + ).where( + loan_doc.docstatus == 1 + ).where( + account == filters.get('account') + ).where( + posting_date > getdate(filters.get('report_date')) + ).where( + ifnull(loan_doc.clearance_date, '4000-01-01') <= getdate(filters.get('report_date')) + ).run()[0][0] + + total_amount += flt(amount) + + return amount def get_balance_row(label, amount, account_currency): if amount > 0: diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py index bf668ab779..621de825ea 100644 --- a/erpnext/accounts/report/tax_detail/test_tax_detail.py +++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py @@ -61,7 +61,7 @@ class TestTaxDetail(unittest.TestCase): # Create GL Entries: db_doc.submit() else: - db_doc.insert() + db_doc.insert(ignore_if_duplicate=True) except frappe.exceptions.DuplicateEntryError: pass diff --git a/erpnext/accounts/test/test_reports.py b/erpnext/accounts/test/test_reports.py index 78c109ab94..4ed966dcb9 100644 --- a/erpnext/accounts/test/test_reports.py +++ b/erpnext/accounts/test/test_reports.py @@ -39,10 +39,11 @@ class TestReports(unittest.TestCase): def test_execute_all_accounts_reports(self): """Test that all script report in stock modules are executable with supported filters""" for report, filter in REPORT_FILTER_TEST_CASES: - execute_script_report( - report_name=report, - module="Accounts", - filters=filter, - default_filters=DEFAULT_FILTERS, - optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, - ) + with self.subTest(report=report): + execute_script_report( + report_name=report, + module="Accounts", + filters=filter, + default_filters=DEFAULT_FILTERS, + optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, + ) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 39e84e3cef..b17b90ba6e 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -847,7 +847,7 @@ def create_payment_gateway_account(gateway, payment_channel="Email"): "payment_account": bank_account.name, "currency": bank_account.account_currency, "payment_channel": payment_channel - }).insert(ignore_permissions=True) + }).insert(ignore_permissions=True, ignore_if_duplicate=True) except frappe.DuplicateEntryError: # already exists, due to a reinstall? diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index ddbff89fc7..ffd1065efc 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1280,7 +1280,7 @@ def create_asset(**args): if not args.do_not_save: try: - asset.save() + asset.insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass @@ -1321,7 +1321,7 @@ def create_fixed_asset_item(item_code=None, auto_create_assets=1, is_grouped_ass "is_grouped_asset": is_grouped_asset, "asset_naming_series": naming_series }) - item.insert() + item.insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass return item diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py index 3d19fa39d1..2f52248edb 100644 --- a/erpnext/assets/doctype/asset_category/test_asset_category.py +++ b/erpnext/assets/doctype/asset_category/test_asset_category.py @@ -23,7 +23,7 @@ class TestAssetCategory(unittest.TestCase): }) try: - asset_category.insert() + asset_category.insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass diff --git a/erpnext/buying/doctype/supplier/test_supplier.py b/erpnext/buying/doctype/supplier/test_supplier.py index 13fe9df13e..0fb81b2578 100644 --- a/erpnext/buying/doctype/supplier/test_supplier.py +++ b/erpnext/buying/doctype/supplier/test_supplier.py @@ -14,151 +14,150 @@ test_records = frappe.get_test_records('Supplier') class TestSupplier(unittest.TestCase): - def test_get_supplier_group_details(self): - doc = frappe.new_doc("Supplier Group") - doc.supplier_group_name = "_Testing Supplier Group" - doc.payment_terms = "_Test Payment Term Template 3" - doc.accounts = [] - test_account_details = { - "company": "_Test Company", - "account": "Creditors - _TC", - } - doc.append("accounts", test_account_details) - doc.save() - s_doc = frappe.new_doc("Supplier") - s_doc.supplier_name = "Testing Supplier" - s_doc.supplier_group = "_Testing Supplier Group" - s_doc.payment_terms = "" - s_doc.accounts = [] - s_doc.insert() - s_doc.get_supplier_group_details() - self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3") - self.assertEqual(s_doc.accounts[0].company, "_Test Company") - self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC") - s_doc.delete() - doc.delete() + def test_get_supplier_group_details(self): + doc = frappe.new_doc("Supplier Group") + doc.supplier_group_name = "_Testing Supplier Group" + doc.payment_terms = "_Test Payment Term Template 3" + doc.accounts = [] + test_account_details = { + "company": "_Test Company", + "account": "Creditors - _TC", + } + doc.append("accounts", test_account_details) + doc.save() + s_doc = frappe.new_doc("Supplier") + s_doc.supplier_name = "Testing Supplier" + s_doc.supplier_group = "_Testing Supplier Group" + s_doc.payment_terms = "" + s_doc.accounts = [] + s_doc.insert() + s_doc.get_supplier_group_details() + self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3") + self.assertEqual(s_doc.accounts[0].company, "_Test Company") + self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC") + s_doc.delete() + doc.delete() - def test_supplier_default_payment_terms(self): - # Payment Term based on Days after invoice date - frappe.db.set_value( - "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 3") + def test_supplier_default_payment_terms(self): + # Payment Term based on Days after invoice date + frappe.db.set_value( + "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 3") - due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2016-02-21") + due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2016-02-21") - due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2017-02-21") + due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2017-02-21") - # Payment Term based on last day of month - frappe.db.set_value( - "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 1") + # Payment Term based on last day of month + frappe.db.set_value( + "Supplier", "_Test Supplier With Template 1", "payment_terms", "_Test Payment Term Template 1") - due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2016-02-29") + due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2016-02-29") - due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2017-02-28") + due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2017-02-28") - frappe.db.set_value("Supplier", "_Test Supplier With Template 1", "payment_terms", "") + frappe.db.set_value("Supplier", "_Test Supplier With Template 1", "payment_terms", "") - # Set credit limit for the supplier group instead of supplier and evaluate the due date - frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 3") + # Set credit limit for the supplier group instead of supplier and evaluate the due date + frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 3") - due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2016-02-21") + due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2016-02-21") - # Payment terms for Supplier Group instead of supplier and evaluate the due date - frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 1") + # Payment terms for Supplier Group instead of supplier and evaluate the due date + frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "_Test Payment Term Template 1") - # Leap year - due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2016-02-29") - # # Non Leap year - due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") - self.assertEqual(due_date, "2017-02-28") + # Leap year + due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2016-02-29") + # # Non Leap year + due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier With Template 1") + self.assertEqual(due_date, "2017-02-28") - # Supplier with no default Payment Terms Template - frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "") - frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "") + # Supplier with no default Payment Terms Template + frappe.db.set_value("Supplier Group", "_Test Supplier Group", "payment_terms", "") + frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", "") - due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier") - self.assertEqual(due_date, "2016-01-22") - # # Non Leap year - due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier") - self.assertEqual(due_date, "2017-01-22") + due_date = get_due_date("2016-01-22", "Supplier", "_Test Supplier") + self.assertEqual(due_date, "2016-01-22") + # # Non Leap year + due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier") + self.assertEqual(due_date, "2017-01-22") - def test_supplier_disabled(self): - make_test_records("Item") + def test_supplier_disabled(self): + make_test_records("Item") - frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1) + frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1) - from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order + from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order - po = create_purchase_order(do_not_save=True) + po = create_purchase_order(do_not_save=True) - self.assertRaises(PartyDisabled, po.save) + self.assertRaises(PartyDisabled, po.save) - frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0) + frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0) - po.save() + po.save() - def test_supplier_country(self): - # Test that country field exists in Supplier DocType - supplier = frappe.get_doc('Supplier', '_Test Supplier with Country') - self.assertTrue('country' in supplier.as_dict()) + def test_supplier_country(self): + # Test that country field exists in Supplier DocType + supplier = frappe.get_doc('Supplier', '_Test Supplier with Country') + self.assertTrue('country' in supplier.as_dict()) - # Test if test supplier field record is 'Greece' - self.assertEqual(supplier.country, "Greece") + # Test if test supplier field record is 'Greece' + self.assertEqual(supplier.country, "Greece") - # Test update Supplier instance country value - supplier = frappe.get_doc('Supplier', '_Test Supplier') - supplier.country = 'Greece' - supplier.save() - self.assertEqual(supplier.country, "Greece") + # Test update Supplier instance country value + supplier = frappe.get_doc('Supplier', '_Test Supplier') + supplier.country = 'Greece' + supplier.save() + self.assertEqual(supplier.country, "Greece") - def test_party_details_tax_category(self): - from erpnext.accounts.party import get_party_details + def test_party_details_tax_category(self): + from erpnext.accounts.party import get_party_details - frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing") + frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing") - # Tax Category without Address - details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier") - self.assertEqual(details.tax_category, "_Test Tax Category 1") + # Tax Category without Address + details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier") + self.assertEqual(details.tax_category, "_Test Tax Category 1") - address = frappe.get_doc(dict( - doctype='Address', - address_title='_Test Address With Tax Category', - tax_category='_Test Tax Category 2', - address_type='Billing', - address_line1='Station Road', - city='_Test City', - country='India', - links=[dict( - link_doctype='Supplier', - link_name='_Test Supplier With Tax Category' - )] - )).insert() + address = frappe.get_doc(dict( + doctype='Address', + address_title='_Test Address With Tax Category', + tax_category='_Test Tax Category 2', + address_type='Billing', + address_line1='Station Road', + city='_Test City', + country='India', + links=[dict( + link_doctype='Supplier', + link_name='_Test Supplier With Tax Category' + )] + )).insert() - # Tax Category with Address - details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier") - self.assertEqual(details.tax_category, "_Test Tax Category 2") + # Tax Category with Address + details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier") + self.assertEqual(details.tax_category, "_Test Tax Category 2") - # Rollback - address.delete() + # Rollback + address.delete() def create_supplier(**args): - args = frappe._dict(args) + args = frappe._dict(args) - try: - doc = frappe.get_doc({ - "doctype": "Supplier", - "supplier_name": args.supplier_name, - "supplier_group": args.supplier_group or "Services", - "supplier_type": args.supplier_type or "Company", - "tax_withholding_category": args.tax_withholding_category - }).insert() + if frappe.db.exists("Supplier", args.supplier_name): + return frappe.get_doc("Supplier", args.supplier_name) - return doc + doc = frappe.get_doc({ + "doctype": "Supplier", + "supplier_name": args.supplier_name, + "supplier_group": args.supplier_group or "Services", + "supplier_type": args.supplier_type or "Company", + "tax_withholding_category": args.tax_withholding_category + }).insert() - except frappe.DuplicateEntryError: - return frappe.get_doc("Supplier", args.supplier_name) + return doc diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index d05787fdfb..a94af10cde 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1566,13 +1566,12 @@ def validate_taxes_and_charges(tax): tax.rate = None -def validate_account_head(tax, doc): - company = frappe.get_cached_value('Account', - tax.account_head, 'company') +def validate_account_head(idx, account, company): + account_company = frappe.get_cached_value('Account', account, 'company') - if company != doc.company: + if account_company != company: frappe.throw(_('Row {0}: Account {1} does not belong to Company {2}') - .format(tax.idx, frappe.bold(tax.account_head), frappe.bold(doc.company)), title=_('Invalid Account')) + .format(idx, frappe.bold(account), frappe.bold(company)), title=_('Invalid Account')) def validate_cost_center(tax, doc): diff --git a/erpnext/domains/non_profit.py b/erpnext/domains/non_profit.py deleted file mode 100644 index d9fc5e5df0..0000000000 --- a/erpnext/domains/non_profit.py +++ /dev/null @@ -1,22 +0,0 @@ -data = { - 'desktop_icons': [ - 'Non Profit', - 'Member', - 'Donor', - 'Volunteer', - 'Grant Application', - 'Accounts', - 'Buying', - 'HR', - 'ToDo' - ], - 'restricted_roles': [ - 'Non Profit Manager', - 'Non Profit Member', - 'Non Profit Portal User' - ], - 'modules': [ - 'Non Profit' - ], - 'default_portal_role': 'Non Profit Manager' -} diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py index 007bf8b348..cfc3c7b357 100644 --- a/erpnext/e_commerce/product_data_engine/query.py +++ b/erpnext/e_commerce/product_data_engine/query.py @@ -264,7 +264,7 @@ class ProductQuery: customer = get_customer(silent=True) if customer: quotation = frappe.get_all("Quotation", fields=["name"], filters= - {"party_name": customer, "order_type": "Shopping Cart", "docstatus": 0}, + {"party_name": customer, "contact_email": frappe.session.user, "order_type": "Shopping Cart", "docstatus": 0}, order_by="modified desc", limit_page_length=1) if quotation: items = frappe.get_all( @@ -298,4 +298,4 @@ class ProductQuery: # slice results manually result[:self.page_length] - return result \ No newline at end of file + return result diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py index 458cf69af7..372aed0b95 100644 --- a/erpnext/e_commerce/shopping_cart/cart.py +++ b/erpnext/e_commerce/shopping_cart/cart.py @@ -310,7 +310,7 @@ def _get_cart_quotation(party=None): party = get_party() quotation = frappe.get_all("Quotation", fields=["name"], filters= - {"party_name": party.name, "order_type": "Shopping Cart", "docstatus": 0}, + {"party_name": party.name, "contact_email": frappe.session.user, "order_type": "Shopping Cart", "docstatus": 0}, order_by="modified desc", limit_page_length=1) if quotation: diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py index 8519e68d09..37b3672806 100644 --- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py +++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py @@ -57,13 +57,19 @@ class TestShoppingCart(unittest.TestCase): return quotation def test_get_cart_customer(self): - self.login_as_customer() + def validate_quotation(): + # test if quotation with customer is fetched + quotation = _get_cart_quotation() + self.assertEqual(quotation.quotation_to, "Customer") + self.assertEqual(quotation.party_name, "_Test Customer") + self.assertEqual(quotation.contact_email, frappe.session.user) + return quotation - # test if quotation with customer is fetched - quotation = _get_cart_quotation() - self.assertEqual(quotation.quotation_to, "Customer") - self.assertEqual(quotation.party_name, "_Test Customer") - self.assertEqual(quotation.contact_email, frappe.session.user) + self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer") + validate_quotation() + + self.login_as_customer() + quotation = validate_quotation() return quotation @@ -175,7 +181,7 @@ class TestShoppingCart(unittest.TestCase): def create_tax_rule(self): tax_rule = frappe.get_test_records("Tax Rule")[0] try: - frappe.get_doc(tax_rule).insert() + frappe.get_doc(tax_rule).insert(ignore_if_duplicate=True) except (frappe.DuplicateEntryError, ConflictingTaxRule): pass @@ -254,10 +260,9 @@ class TestShoppingCart(unittest.TestCase): self.create_user_if_not_exists("test_cart_user@example.com") frappe.set_user("test_cart_user@example.com") - def login_as_customer(self): - self.create_user_if_not_exists("test_contact_customer@example.com", - "_Test Contact For _Test Customer") - frappe.set_user("test_contact_customer@example.com") + def login_as_customer(self, email="test_contact_customer@example.com", name="_Test Contact For _Test Customer"): + self.create_user_if_not_exists(email, name) + frappe.set_user(email) def clear_existing_quotations(self): quotations = frappe.get_all("Quotation", filters={ diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js index 68e7780039..4526585175 100644 --- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js +++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js @@ -3,6 +3,10 @@ frappe.provide("education"); frappe.ui.form.on('Student Attendance Tool', { + setup: (frm) => { + frm.students_area = $('
') + .appendTo(frm.fields_dict.students_html.wrapper); + }, onload: function(frm) { frm.set_query("student_group", function() { return { @@ -34,6 +38,7 @@ frappe.ui.form.on('Student Attendance Tool', { student_group: function(frm) { if ((frm.doc.student_group && frm.doc.date) || frm.doc.course_schedule) { + frm.students_area.find('.student-attendance-checks').html(`
Fetching...
`); var method = "erpnext.education.doctype.student_attendance_tool.student_attendance_tool.get_student_attendance_records"; frappe.call({ @@ -62,10 +67,6 @@ frappe.ui.form.on('Student Attendance Tool', { }, get_students: function(frm, students) { - if (!frm.students_area) { - frm.students_area = $('
') - .appendTo(frm.fields_dict.students_html.wrapper); - } students = students || []; frm.students_editor = new education.StudentsEditor(frm, frm.students_area, students); } @@ -163,16 +164,26 @@ education.StudentsEditor = class StudentsEditor { ); }); - var htmls = students.map(function(student) { - return frappe.render_template("student_button", { - student: student.student, - student_name: student.student_name, - group_roll_number: student.group_roll_number, - status: student.status - }) - }); + // make html grid of students + let student_html = ''; + for (let student of students) { + student_html += `
+
+ +
+
`; + } - $(htmls.join("")).appendTo(me.wrapper); + $(`
${student_html}
`).appendTo(me.wrapper); } show_empty_state() { diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py index 7deb6b18da..92bb20ca52 100644 --- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py +++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py @@ -24,24 +24,24 @@ def get_student_attendance_records(based_on, date=None, student_group=None, cour student_list = frappe.get_all("Student Group Student", fields=["student", "student_name", "group_roll_number"], filters={"parent": student_group, "active": 1}, order_by= "group_roll_number") - table = frappe.qb.DocType("Student Attendance") + StudentAttendance = frappe.qb.DocType("Student Attendance") if course_schedule: student_attendance_list = ( - frappe.qb.from_(table) - .select(table.student, table.status) + frappe.qb.from_(StudentAttendance) + .select(StudentAttendance.student, StudentAttendance.status) .where( - (table.course_schedule == course_schedule) + (StudentAttendance.course_schedule == course_schedule) ) ).run(as_dict=True) else: student_attendance_list = ( - frappe.qb.from_(table) - .select(table.student, table.status) + frappe.qb.from_(StudentAttendance) + .select(StudentAttendance.student, StudentAttendance.status) .where( - (table.student_group == student_group) - & (table.date == date) - & (table.course_schedule == "") | (table.course_schedule.isnull()) + (StudentAttendance.student_group == student_group) + & (StudentAttendance.date == date) + & ((StudentAttendance.course_schedule == "") | (StudentAttendance.course_schedule.isnull())) ) ).run(as_dict=True) diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py index 54ed6f7d11..26bd19f010 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py @@ -82,7 +82,7 @@ class TallyMigration(Document): "is_private": True }) try: - f.insert() + f.insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass setattr(self, key, f.file_url) diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index a4e21579e3..14c86d5632 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -8,10 +8,6 @@ from frappe.utils import cint, flt from erpnext import get_default_company, get_region -TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") -SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head") -TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") -TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax") SUPPORTED_COUNTRY_CODES = ["AT", "AU", "BE", "BG", "CA", "CY", "CZ", "DE", "DK", "EE", "ES", "FI", "FR", "GB", "GR", "HR", "HU", "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PL", "PT", "RO", "SE", "SI", "SK", "US"] @@ -35,12 +31,14 @@ def get_client(): if api_key and api_url: client = taxjar.Client(api_key=api_key, api_url=api_url) client.set_api_config('headers', { - 'x-api-version': '2020-08-07' + 'x-api-version': '2022-01-24' }) return client def create_transaction(doc, method): + TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") + """Create an order transaction in TaxJar""" if not TAXJAR_CREATE_TRANSACTIONS: @@ -51,6 +49,7 @@ def create_transaction(doc, method): if not client: return + TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") sales_tax = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == TAX_ACCOUNT_HEAD]) if not sales_tax: @@ -79,6 +78,7 @@ def create_transaction(doc, method): def delete_transaction(doc, method): """Delete an existing TaxJar order transaction""" + TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") if not TAXJAR_CREATE_TRANSACTIONS: return @@ -92,6 +92,8 @@ def delete_transaction(doc, method): def get_tax_data(doc): + SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head") + from_address = get_company_address_details(doc) from_shipping_state = from_address.get("state") from_country_code = frappe.db.get_value("Country", from_address.country, "code") @@ -113,20 +115,20 @@ def get_tax_data(doc): to_shipping_state = get_state_code(to_address, 'Shipping') tax_dict = { - 'from_country': from_country_code, - 'from_zip': from_address.pincode, - 'from_state': from_shipping_state, - 'from_city': from_address.city, - 'from_street': from_address.address_line1, - 'to_country': to_country_code, - 'to_zip': to_address.pincode, - 'to_city': to_address.city, - 'to_street': to_address.address_line1, - 'to_state': to_shipping_state, - 'shipping': shipping, - 'amount': doc.net_total, - 'plugin': 'erpnext', - 'line_items': line_items + "from_country": from_country_code, + "from_zip": from_address.pincode, + "from_state": from_shipping_state, + "from_city": from_address.city, + "from_street": from_address.address_line1, + "to_country": to_country_code, + "to_zip": to_address.pincode, + "to_city": to_address.city, + "to_street": to_address.address_line1, + "to_state": to_shipping_state, + "shipping": shipping, + "amount": doc.net_total, + "plugin": "erpnext", + "line_items": line_items } return tax_dict @@ -156,6 +158,9 @@ def get_line_item_dict(item, docstatus): return tax_dict def set_sales_tax(doc, method): + TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") + TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax") + if not TAXJAR_CALCULATE_TAX: return @@ -206,6 +211,7 @@ def set_sales_tax(doc, method): doc.run_method("calculate_taxes_and_totals") def check_for_nexus(doc, tax_dict): + TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") if not frappe.db.get_value('TaxJar Nexus', {'region_code': tax_dict["to_state"]}): for item in doc.get("items"): item.tax_collectable = flt(0) @@ -218,6 +224,8 @@ def check_for_nexus(doc, tax_dict): def check_sales_tax_exemption(doc): # if the party is exempt from sales tax, then set all tax account heads to zero + TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") + sales_tax_exempted = hasattr(doc, "exempt_from_sales_tax") and doc.exempt_from_sales_tax \ or frappe.db.has_column("Customer", "exempt_from_sales_tax") \ and frappe.db.get_value("Customer", doc.customer, "exempt_from_sales_tax") diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 38fa6916a5..f8c42887fd 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -68,7 +68,6 @@ domains = { 'Distribution': 'erpnext.domains.distribution', 'Education': 'erpnext.domains.education', 'Manufacturing': 'erpnext.domains.manufacturing', - 'Non Profit': 'erpnext.domains.non_profit', 'Retail': 'erpnext.domains.retail', 'Services': 'erpnext.domains.services', } @@ -175,7 +174,6 @@ standard_portal_menu_items = [ {"title": _("Fees"), "route": "/fees", "reference_doctype": "Fees", "role":"Student"}, {"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"}, {"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission", "role": "Student"}, - {"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application", "role": "Non Profit Portal User"}, {"title": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"}, {"title": _("Appointment Booking"), "route": "/book_appointment"}, ] @@ -369,7 +367,6 @@ scheduler_events = { "erpnext.selling.doctype.quotation.quotation.set_expired_status", "erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status", "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email", - "erpnext.non_profit.doctype.membership.membership.set_expired_status", "erpnext.hr.doctype.interview.interview.send_daily_feedback_reminder" ], "daily_long": [ @@ -563,19 +560,6 @@ global_search_doctypes = { {'doctype': 'Assessment Code', 'index': 39}, {'doctype': 'Discussion', 'index': 40}, ], - "Non Profit": [ - {'doctype': 'Certified Consultant', 'index': 1}, - {'doctype': 'Certification Application', 'index': 2}, - {'doctype': 'Volunteer', 'index': 3}, - {'doctype': 'Membership', 'index': 4}, - {'doctype': 'Member', 'index': 5}, - {'doctype': 'Donor', 'index': 6}, - {'doctype': 'Chapter', 'index': 7}, - {'doctype': 'Grant Application', 'index': 8}, - {'doctype': 'Volunteer Type', 'index': 9}, - {'doctype': 'Donor Type', 'index': 10}, - {'doctype': 'Membership Type', 'index': 11} - ], } additional_timeline_content = { diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py index ed0bfcf0d5..71300c40b0 100644 --- a/erpnext/hr/doctype/department/department.py +++ b/erpnext/hr/doctype/department/department.py @@ -32,7 +32,7 @@ class Department(NestedSet): return new def on_update(self): - if not frappe.local.flags.ignore_update_nsm: + if not (frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard): super(Department, self).on_update() def on_trash(self): diff --git a/erpnext/hr/doctype/department/test_records.json b/erpnext/hr/doctype/department/test_records.json index 654925ef93..e3421f28b8 100644 --- a/erpnext/hr/doctype/department/test_records.json +++ b/erpnext/hr/doctype/department/test_records.json @@ -1,4 +1,4 @@ [ - {"doctype":"Department", "department_name":"_Test Department", "company": "_Test Company"}, - {"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company"} + {"doctype":"Department", "department_name":"_Test Department", "company": "_Test Company", "parent_department": "All Departments"}, + {"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company", "parent_department": "All Departments"} ] \ No newline at end of file diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index a2df26c3e2..6e52eb97ca 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -142,7 +142,7 @@ class Employee(NestedSet): "file_url": self.image, "attached_to_doctype": "User", "attached_to_name": self.user_id - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: # already exists pass diff --git a/erpnext/hr/doctype/exit_interview/exit_interview.py b/erpnext/hr/doctype/exit_interview/exit_interview.py index 30e19f1c9b..59fb2fd9ca 100644 --- a/erpnext/hr/doctype/exit_interview/exit_interview.py +++ b/erpnext/hr/doctype/exit_interview/exit_interview.py @@ -128,4 +128,4 @@ def show_email_summary(email_success, email_failure): message += _('{0} due to missing email information for employee(s): {1}').format( frappe.bold('Sending Failed'), ', '.join(email_failure)) - frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True) \ No newline at end of file + frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True) diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py index acd50f278c..abb288723c 100644 --- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py @@ -82,7 +82,7 @@ def get_vehicle(employee_id): "vehicle_value": flt(500000) }) try: - vehicle.insert() + vehicle.insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass return license_plate diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json index 7811d56a75..50926d7726 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json +++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json @@ -14,11 +14,15 @@ "applicant", "section_break_7", "disbursement_date", + "clearance_date", "column_break_8", "disbursed_amount", "accounting_dimensions_section", "cost_center", - "customer_details_section", + "accounting_details", + "disbursement_account", + "column_break_16", + "loan_account", "bank_account", "disbursement_references_section", "reference_date", @@ -106,11 +110,6 @@ "fieldtype": "Section Break", "label": "Disbursement Details" }, - { - "fieldname": "customer_details_section", - "fieldtype": "Section Break", - "label": "Customer Details" - }, { "fetch_from": "against_loan.applicant_type", "fieldname": "applicant_type", @@ -149,15 +148,48 @@ "fieldname": "reference_number", "fieldtype": "Data", "label": "Reference Number" + }, + { + "fieldname": "clearance_date", + "fieldtype": "Date", + "label": "Clearance Date", + "no_copy": 1, + "read_only": 1 + }, + { + "fieldname": "accounting_details", + "fieldtype": "Section Break", + "label": "Accounting Details" + }, + { + "fetch_from": "against_loan.disbursement_account", + "fieldname": "disbursement_account", + "fieldtype": "Link", + "label": "Disbursement Account", + "options": "Account", + "read_only": 1 + }, + { + "fieldname": "column_break_16", + "fieldtype": "Column Break" + }, + { + "fetch_from": "against_loan.loan_account", + "fieldname": "loan_account", + "fieldtype": "Link", + "label": "Loan Account", + "options": "Account", + "read_only": 1 } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-04-19 18:09:32.175355", + "modified": "2022-02-17 18:23:44.157598", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Disbursement", + "naming_rule": "Expression (old style)", "owner": "Administrator", "permissions": [ { @@ -194,5 +226,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py index df3aadfb18..54a03b92b5 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py +++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py @@ -42,9 +42,6 @@ class LoanDisbursement(AccountsController): if not self.posting_date: self.posting_date = self.disbursement_date or nowdate() - if not self.bank_account and self.applicant_type == "Customer": - self.bank_account = frappe.db.get_value("Customer", self.applicant, "default_bank_account") - def validate_disbursal_amount(self): possible_disbursal_amount = get_disbursal_amount(self.against_loan) @@ -117,12 +114,11 @@ class LoanDisbursement(AccountsController): def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] - loan_details = frappe.get_doc("Loan", self.against_loan) gle_map.append( self.get_gl_dict({ - "account": loan_details.loan_account, - "against": loan_details.disbursement_account, + "account": self.loan_account, + "against": self.disbursement_account, "debit": self.disbursed_amount, "debit_in_account_currency": self.disbursed_amount, "against_voucher_type": "Loan", @@ -137,8 +133,8 @@ class LoanDisbursement(AccountsController): gle_map.append( self.get_gl_dict({ - "account": loan_details.disbursement_account, - "against": loan_details.loan_account, + "account": self.disbursement_account, + "against": self.loan_account, "credit": self.disbursed_amount, "credit_in_account_currency": self.disbursed_amount, "against_voucher_type": "Loan", diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json index 93ef217042..480e010b49 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json @@ -1,7 +1,7 @@ { "actions": [], "autoname": "LM-REP-.####", - "creation": "2019-09-03 14:44:39.977266", + "creation": "2022-01-25 10:30:02.767941", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", @@ -13,6 +13,7 @@ "column_break_3", "company", "posting_date", + "clearance_date", "rate_of_interest", "payroll_payable_account", "is_term_loan", @@ -37,7 +38,12 @@ "total_penalty_paid", "total_interest_paid", "repayment_details", - "amended_from" + "amended_from", + "accounting_details_section", + "payment_account", + "penalty_income_account", + "column_break_36", + "loan_account" ], "fields": [ { @@ -260,12 +266,52 @@ "fieldname": "repay_from_salary", "fieldtype": "Check", "label": "Repay From Salary" + }, + { + "fieldname": "clearance_date", + "fieldtype": "Date", + "label": "Clearance Date", + "no_copy": 1, + "read_only": 1 + }, + { + "fieldname": "accounting_details_section", + "fieldtype": "Section Break", + "label": "Accounting Details" + }, + { + "fetch_from": "against_loan.payment_account", + "fieldname": "payment_account", + "fieldtype": "Link", + "label": "Repayment Account", + "options": "Account", + "read_only": 1 + }, + { + "fieldname": "column_break_36", + "fieldtype": "Column Break" + }, + { + "fetch_from": "against_loan.loan_account", + "fieldname": "loan_account", + "fieldtype": "Link", + "label": "Loan Account", + "options": "Account", + "read_only": 1 + }, + { + "fetch_from": "against_loan.penalty_income_account", + "fieldname": "penalty_income_account", + "fieldtype": "Link", + "hidden": 1, + "label": "Penalty Income Account", + "options": "Account" } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-01-06 01:51:06.707782", + "modified": "2022-02-18 19:10:07.742298", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Repayment", diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index f3ed611255..67c2b1ee14 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -310,7 +310,6 @@ class LoanRepayment(AccountsController): def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] - loan_details = frappe.get_doc("Loan", self.against_loan) if self.shortfall_amount and self.amount_paid > self.shortfall_amount: remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(self.shortfall_amount, @@ -323,13 +322,13 @@ class LoanRepayment(AccountsController): if self.repay_from_salary: payment_account = self.payroll_payable_account else: - payment_account = loan_details.payment_account + payment_account = self.payment_account if self.total_penalty_paid: gle_map.append( self.get_gl_dict({ - "account": loan_details.loan_account, - "against": loan_details.payment_account, + "account": self.loan_account, + "against": payment_account, "debit": self.total_penalty_paid, "debit_in_account_currency": self.total_penalty_paid, "against_voucher_type": "Loan", @@ -344,8 +343,8 @@ class LoanRepayment(AccountsController): gle_map.append( self.get_gl_dict({ - "account": loan_details.penalty_income_account, - "against": loan_details.loan_account, + "account": self.penalty_income_account, + "against": self.loan_account, "credit": self.total_penalty_paid, "credit_in_account_currency": self.total_penalty_paid, "against_voucher_type": "Loan", @@ -359,8 +358,7 @@ class LoanRepayment(AccountsController): gle_map.append( self.get_gl_dict({ "account": payment_account, - "against": loan_details.loan_account + ", " + loan_details.interest_income_account - + ", " + loan_details.penalty_income_account, + "against": self.loan_account + ", " + self.penalty_income_account, "debit": self.amount_paid, "debit_in_account_currency": self.amount_paid, "against_voucher_type": "Loan", @@ -368,16 +366,16 @@ class LoanRepayment(AccountsController): "remarks": remarks, "cost_center": self.cost_center, "posting_date": getdate(self.posting_date), - "party_type": loan_details.applicant_type if self.repay_from_salary else '', - "party": loan_details.applicant if self.repay_from_salary else '' + "party_type": self.applicant_type if self.repay_from_salary else '', + "party": self.applicant if self.repay_from_salary else '' }) ) gle_map.append( self.get_gl_dict({ - "account": loan_details.loan_account, - "party_type": loan_details.applicant_type, - "party": loan_details.applicant, + "account": self.loan_account, + "party_type": self.applicant_type, + "party": self.applicant, "against": payment_account, "credit": self.amount_paid, "credit_in_account_currency": self.amount_paid, diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index d88e10a564..2359815813 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -9,6 +9,7 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import ( get_sales_orders, get_warehouse_list, ) +from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry @@ -466,26 +467,29 @@ class TestProductionPlan(ERPNextTestCase): bom = make_bom(item=item, raw_materials=raw_materials) # Create Production Plan - pln = create_production_plan(item_code=bom.item, planned_qty=10) + pln = create_production_plan(item_code=bom.item, planned_qty=5) # All the created Work Orders wo_list = [] - # Create and Submit 1st Work Order for 5 qty - create_work_order(item, pln, 5) + # Create and Submit 1st Work Order for 3 qty + create_work_order(item, pln, 3) + pln.reload() + self.assertEqual(pln.po_items[0].ordered_qty, 3) + + # Create and Submit 2nd Work Order for 2 qty + create_work_order(item, pln, 2) pln.reload() self.assertEqual(pln.po_items[0].ordered_qty, 5) - # Create and Submit 2nd Work Order for 3 qty - create_work_order(item, pln, 3) - pln.reload() - self.assertEqual(pln.po_items[0].ordered_qty, 8) + # Overproduction + self.assertRaises(OverProductionError, create_work_order, item=item, pln=pln, qty=2) # Cancel 1st Work Order wo1 = frappe.get_doc("Work Order", wo_list[0]) wo1.cancel() pln.reload() - self.assertEqual(pln.po_items[0].ordered_qty, 3) + self.assertEqual(pln.po_items[0].ordered_qty, 2) # Cancel 2nd Work Order wo2 = frappe.get_doc("Work Order", wo_list[1]) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index ed6a0299ef..e1120c723d 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -636,6 +636,21 @@ class WorkOrder(Document): if not self.qty > 0: frappe.throw(_("Quantity to Manufacture must be greater than 0.")) + if self.production_plan and self.production_plan_item: + qty_dict = frappe.db.get_value("Production Plan Item", self.production_plan_item, ["planned_qty", "ordered_qty"], as_dict=1) + + allowance_qty =flt(frappe.db.get_single_value("Manufacturing Settings", + "overproduction_percentage_for_work_order"))/100 * qty_dict.get("planned_qty", 0) + + max_qty = qty_dict.get("planned_qty", 0) + allowance_qty - qty_dict.get("ordered_qty", 0) + + if max_qty < 1: + frappe.throw(_("Cannot produce more item for {0}") + .format(self.production_item), OverProductionError) + elif self.qty > max_qty: + frappe.throw(_("Cannot produce more than {0} items for {1}") + .format(max_qty, self.production_item), OverProductionError) + def validate_transfer_against(self): if not self.docstatus == 1: # let user configure operations until they're ready to submit diff --git a/erpnext/manufacturing/report/test_reports.py b/erpnext/manufacturing/report/test_reports.py index 9f51ded6c7..e436fdca64 100644 --- a/erpnext/manufacturing/report/test_reports.py +++ b/erpnext/manufacturing/report/test_reports.py @@ -55,10 +55,11 @@ class TestManufacturingReports(unittest.TestCase): def test_execute_all_manufacturing_reports(self): """Test that all script report in manufacturing modules are executable with supported filters""" for report, filter in REPORT_FILTER_TEST_CASES: - execute_script_report( - report_name=report, - module="Manufacturing", - filters=filter, - default_filters=DEFAULT_FILTERS, - optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, - ) + with self.subTest(report=report): + execute_script_report( + report_name=report, + module="Manufacturing", + filters=filter, + default_filters=DEFAULT_FILTERS, + optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, + ) diff --git a/erpnext/modules.txt b/erpnext/modules.txt index 8c79ee5c9a..c6b3159e0f 100644 --- a/erpnext/modules.txt +++ b/erpnext/modules.txt @@ -15,7 +15,6 @@ Maintenance Education Regional ERPNext Integrations -Non Profit Quality Management Communication Loan Management diff --git a/erpnext/non_profit/__init__.py b/erpnext/non_profit/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/__init__.py b/erpnext/non_profit/doctype/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/certification_application/__init__.py b/erpnext/non_profit/doctype/certification_application/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.js b/erpnext/non_profit/doctype/certification_application/certification_application.js deleted file mode 100644 index 1e6a9a4b01..0000000000 --- a/erpnext/non_profit/doctype/certification_application/certification_application.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Certification Application', { - refresh: function(frm) { - - } -}); diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.json b/erpnext/non_profit/doctype/certification_application/certification_application.json deleted file mode 100644 index f562fa6734..0000000000 --- a/erpnext/non_profit/doctype/certification_application/certification_application.json +++ /dev/null @@ -1,323 +0,0 @@ -{ - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "NPO-CAPP-.YYYY.-.#####", - "beta": 0, - "creation": "2018-06-08 16:12:42.091729", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "name_of_applicant", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Name of Applicant", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Email", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "certification_status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Certification Status", - "length": 0, - "no_copy": 0, - "options": "Yet to appear\nCertified\nNot Certified", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "paid", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Paid", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "USD\nINR", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amount", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-04 03:36:35.337403", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Certification Application", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/certification_application/certification_application.py b/erpnext/non_profit/doctype/certification_application/certification_application.py deleted file mode 100644 index cbbe191fba..0000000000 --- a/erpnext/non_profit/doctype/certification_application/certification_application.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class CertificationApplication(Document): - pass diff --git a/erpnext/non_profit/doctype/certification_application/test_certification_application.py b/erpnext/non_profit/doctype/certification_application/test_certification_application.py deleted file mode 100644 index 8687b4daf4..0000000000 --- a/erpnext/non_profit/doctype/certification_application/test_certification_application.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestCertificationApplication(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/certified_consultant/__init__.py b/erpnext/non_profit/doctype/certified_consultant/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js deleted file mode 100644 index cd004c3489..0000000000 --- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Certified Consultant', { - refresh: function(frm) { - - } -}); diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json deleted file mode 100644 index d77f1b2569..0000000000 --- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.json +++ /dev/null @@ -1,724 +0,0 @@ -{ - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "NPO-CONS-.YYYY.-.#####", - "beta": 0, - "creation": "2018-06-13 17:27:19.838334", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "name_of_consultant", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Name of Consultant", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "country", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Country", - "length": 0, - "no_copy": 0, - "options": "Country", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Email", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "phone", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Phone", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "website_url", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Website", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "certification_application", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Certification Application", - "length": 0, - "no_copy": 0, - "options": "Certification Application", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Certification Validity", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "from_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "From", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_beak2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "to_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "To", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break2", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "introduction", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Introduction", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "details", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break3", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discuss_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Discuss ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "github_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "GitHub ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "show_in_website", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show in Website", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-04 03:36:47.386618", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Certified Consultant", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py deleted file mode 100644 index 47361cc39e..0000000000 --- a/erpnext/non_profit/doctype/certified_consultant/certified_consultant.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class CertifiedConsultant(Document): - pass diff --git a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py b/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py deleted file mode 100644 index d10353c1e4..0000000000 --- a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestCertifiedConsultant(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/chapter/__init__.py b/erpnext/non_profit/doctype/chapter/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/chapter/chapter.js b/erpnext/non_profit/doctype/chapter/chapter.js deleted file mode 100644 index c8b6d4a644..0000000000 --- a/erpnext/non_profit/doctype/chapter/chapter.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Chapter', { - refresh: function() { - - } -}); diff --git a/erpnext/non_profit/doctype/chapter/chapter.json b/erpnext/non_profit/doctype/chapter/chapter.json deleted file mode 100644 index 86cba9a178..0000000000 --- a/erpnext/non_profit/doctype/chapter/chapter.json +++ /dev/null @@ -1,397 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 1, - "allow_import": 0, - "allow_rename": 1, - "autoname": "prompt", - "beta": 0, - "creation": "2017-09-14 13:36:03.904702", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "chapter_head", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Chapter Head", - "length": 0, - "no_copy": 0, - "options": "Member", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "region", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Region", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "introduction", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Introduction", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "meetup_embed_html", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Meetup Embed HTML", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "chapters/chapter_name\nleave blank automatically set after saving chapter.", - "fieldname": "route", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Route", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "published", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Published", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "chapter_members", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Chapter Members", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "members", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Members", - "length": 0, - "no_copy": 0, - "options": "Chapter Member", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 1, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_published_field": "published", - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-12-14 12:59:31.424240", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Chapter", - "name_case": "Title Case", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "route": "chapters", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/chapter/chapter.py b/erpnext/non_profit/doctype/chapter/chapter.py deleted file mode 100644 index c01b1ef3e4..0000000000 --- a/erpnext/non_profit/doctype/chapter/chapter.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe.website.website_generator import WebsiteGenerator - - -class Chapter(WebsiteGenerator): - _website = frappe._dict( - condition_field = "published", - ) - - def get_context(self, context): - context.no_cache = True - context.show_sidebar = True - context.parents = [dict(label='View All Chapters', - route='chapters', title='View Chapters')] - - def validate(self): - if not self.route: #pylint: disable=E0203 - self.route = 'chapters/' + self.scrub(self.name) - - def enable(self): - chapter = frappe.get_doc('Chapter', frappe.form_dict.name) - chapter.append('members', dict(enable=self.value)) - chapter.save(ignore_permissions=1) - frappe.db.commit() - - -def get_list_context(context): - context.allow_guest = True - context.no_cache = True - context.show_sidebar = True - context.title = 'All Chapters' - context.no_breadcrumbs = True - context.order_by = 'creation desc' - - -@frappe.whitelist() -def leave(title, user_id, leave_reason): - chapter = frappe.get_doc("Chapter", title) - for member in chapter.members: - if member.user == user_id: - member.enabled = 0 - member.leave_reason = leave_reason - chapter.save(ignore_permissions=1) - frappe.db.commit() - return "Thank you for Feedback" diff --git a/erpnext/non_profit/doctype/chapter/templates/chapter.html b/erpnext/non_profit/doctype/chapter/templates/chapter.html deleted file mode 100644 index 321828f73f..0000000000 --- a/erpnext/non_profit/doctype/chapter/templates/chapter.html +++ /dev/null @@ -1,79 +0,0 @@ -{% extends "templates/web.html" %} - -{% block page_content %} -

{{ title }}

-

{{ introduction }}

-{% if meetup_embed_html %} - {{ meetup_embed_html }} -{% endif %} -

Member Details

- -{% if members %} - - {% set index = [1] %} - {% for user in members %} - {% if user.enabled == 1 %} - - - - {% set __ = index.append(1) %} - {% endif %} - {% endfor %} -
-
-
-
-
- {{ index|length }}. {{ frappe.db.get_value('User', user.user, 'full_name') }}
-
-
- {% if user.website_url %} - {{ user.website_url | truncate (50) or '' }} - {% endif %} -
-
-
-

-
- {% if user.introduction %} - {{ user.introduction }} - {% endif %} -
-
- -
-{% else %} -

No member yet.

-{% endif %} - -

Chapter Head

-
- - - {% set doc = frappe.get_doc('Member',chapter_head) %} - - - - - - - - - - - - -
Name{{ doc.member_name }}
Email{{ frappe.db.get_value('User', doc.email, 'email') or '' }}
Phone{{ frappe.db.get_value('User', doc.email, 'phone') or '' }}
-
- -{% if address %} -

Address

-
-

{{ address or ''}}

-
-{% endif %} - -

Join this Chapter

-

Leave this Chapter

- -{% endblock %} diff --git a/erpnext/non_profit/doctype/chapter/templates/chapter_row.html b/erpnext/non_profit/doctype/chapter/templates/chapter_row.html deleted file mode 100644 index cad34fa5be..0000000000 --- a/erpnext/non_profit/doctype/chapter/templates/chapter_row.html +++ /dev/null @@ -1,25 +0,0 @@ -{% if doc.published %} - -{% endif %} diff --git a/erpnext/non_profit/doctype/chapter/test_chapter.py b/erpnext/non_profit/doctype/chapter/test_chapter.py deleted file mode 100644 index 98601efcf2..0000000000 --- a/erpnext/non_profit/doctype/chapter/test_chapter.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestChapter(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/chapter_member/__init__.py b/erpnext/non_profit/doctype/chapter_member/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/chapter_member/chapter_member.json b/erpnext/non_profit/doctype/chapter_member/chapter_member.json deleted file mode 100644 index 478bfd9331..0000000000 --- a/erpnext/non_profit/doctype/chapter_member/chapter_member.json +++ /dev/null @@ -1,199 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2017-09-14 13:38:04.296375", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "user", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "introduction", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Introduction", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "website_url", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Website URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "default": "1", - "fieldname": "enabled", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Enabled", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "leave_reason", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Leave Reason", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-03-07 05:36:51.664816", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Chapter Member", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/chapter_member/chapter_member.py b/erpnext/non_profit/doctype/chapter_member/chapter_member.py deleted file mode 100644 index 80c0446ee5..0000000000 --- a/erpnext/non_profit/doctype/chapter_member/chapter_member.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class ChapterMember(Document): - pass diff --git a/erpnext/non_profit/doctype/donation/__init__.py b/erpnext/non_profit/doctype/donation/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/donation/donation.js b/erpnext/non_profit/doctype/donation/donation.js deleted file mode 100644 index 10e8220144..0000000000 --- a/erpnext/non_profit/doctype/donation/donation.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Donation', { - refresh: function(frm) { - if (frm.doc.docstatus === 1 && !frm.doc.paid) { - frm.add_custom_button(__('Create Payment Entry'), function() { - frm.events.make_payment_entry(frm); - }); - } - }, - - make_payment_entry: function(frm) { - return frappe.call({ - method: 'erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry', - args: { - 'dt': frm.doc.doctype, - 'dn': frm.doc.name - }, - callback: function(r) { - var doc = frappe.model.sync(r.message); - frappe.set_route('Form', doc[0].doctype, doc[0].name); - } - }); - }, -}); diff --git a/erpnext/non_profit/doctype/donation/donation.json b/erpnext/non_profit/doctype/donation/donation.json deleted file mode 100644 index 6759569d54..0000000000 --- a/erpnext/non_profit/doctype/donation/donation.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "actions": [], - "autoname": "naming_series:", - "creation": "2021-02-17 10:28:52.645731", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "naming_series", - "donor", - "donor_name", - "email", - "column_break_4", - "company", - "date", - "payment_details_section", - "paid", - "amount", - "mode_of_payment", - "razorpay_payment_id", - "amended_from" - ], - "fields": [ - { - "fieldname": "donor", - "fieldtype": "Link", - "label": "Donor", - "options": "Donor", - "reqd": 1 - }, - { - "fetch_from": "donor.donor_name", - "fieldname": "donor_name", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Donor Name", - "read_only": 1 - }, - { - "fetch_from": "donor.email", - "fieldname": "email", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Email", - "read_only": 1 - }, - { - "fieldname": "column_break_4", - "fieldtype": "Column Break" - }, - { - "fieldname": "date", - "fieldtype": "Date", - "label": "Date", - "reqd": 1 - }, - { - "fieldname": "payment_details_section", - "fieldtype": "Section Break", - "label": "Payment Details" - }, - { - "fieldname": "amount", - "fieldtype": "Currency", - "label": "Amount", - "reqd": 1 - }, - { - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "label": "Mode of Payment", - "options": "Mode of Payment" - }, - { - "fieldname": "razorpay_payment_id", - "fieldtype": "Data", - "label": "Razorpay Payment ID", - "read_only": 1 - }, - { - "fieldname": "naming_series", - "fieldtype": "Select", - "label": "Naming Series", - "options": "NPO-DTN-.YYYY.-" - }, - { - "default": "0", - "fieldname": "paid", - "fieldtype": "Check", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Paid" - }, - { - "fieldname": "company", - "fieldtype": "Link", - "label": "Company", - "options": "Company", - "reqd": 1 - }, - { - "fieldname": "amended_from", - "fieldtype": "Link", - "label": "Amended From", - "no_copy": 1, - "options": "Donation", - "print_hide": 1, - "read_only": 1 - } - ], - "index_web_pages_for_search": 1, - "is_submittable": 1, - "links": [], - "modified": "2021-03-11 10:53:11.269005", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Donation", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "select": 1, - "share": 1, - "submit": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "select": 1, - "share": 1, - "submit": 1, - "write": 1 - } - ], - "search_fields": "donor_name, email", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "donor_name", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/donation/donation.py b/erpnext/non_profit/doctype/donation/donation.py deleted file mode 100644 index 54bc94b755..0000000000 --- a/erpnext/non_profit/doctype/donation/donation.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import json - -import frappe -from frappe import _ -from frappe.email import sendmail_to_system_managers -from frappe.model.document import Document -from frappe.utils import flt, get_link_to_form, getdate - -from erpnext.non_profit.doctype.membership.membership import verify_signature - - -class Donation(Document): - def validate(self): - if not self.donor or not frappe.db.exists('Donor', self.donor): - # for web forms - user_type = frappe.db.get_value('User', frappe.session.user, 'user_type') - if user_type == 'Website User': - self.create_donor_for_website_user() - else: - frappe.throw(_('Please select a Member')) - - def create_donor_for_website_user(self): - donor_name = frappe.get_value('Donor', dict(email=frappe.session.user)) - - if not donor_name: - user = frappe.get_doc('User', frappe.session.user) - donor = frappe.get_doc(dict( - doctype='Donor', - donor_type=self.get('donor_type'), - email=frappe.session.user, - member_name=user.get_fullname() - )).insert(ignore_permissions=True) - donor_name = donor.name - - if self.get('__islocal'): - self.donor = donor_name - - def on_payment_authorized(self, *args, **kwargs): - self.load_from_db() - self.create_payment_entry() - - def create_payment_entry(self, date=None): - settings = frappe.get_doc('Non Profit Settings') - if not settings.automate_donation_payment_entries: - return - - if not settings.donation_payment_account: - frappe.throw(_('You need to set Payment Account for Donation in {0}').format( - get_link_to_form('Non Profit Settings', 'Non Profit Settings'))) - - from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry - - frappe.flags.ignore_account_permission = True - pe = get_payment_entry(dt=self.doctype, dn=self.name) - frappe.flags.ignore_account_permission = False - pe.paid_from = settings.donation_debit_account - pe.paid_to = settings.donation_payment_account - pe.posting_date = date or getdate() - pe.reference_no = self.name - pe.reference_date = date or getdate() - pe.flags.ignore_mandatory = True - pe.insert() - pe.submit() - - -@frappe.whitelist(allow_guest=True) -def capture_razorpay_donations(*args, **kwargs): - """ - Creates Donation from Razorpay Webhook Request Data on payment.captured event - Creates Donor from email if not found - """ - data = frappe.request.get_data(as_text=True) - - try: - verify_signature(data, endpoint='Donation') - except Exception as e: - log = frappe.log_error(e, 'Donation Webhook Verification Error') - notify_failure(log) - return { 'status': 'Failed', 'reason': e } - - if isinstance(data, str): - data = json.loads(data) - data = frappe._dict(data) - - payment = data.payload.get('payment', {}).get('entity', {}) - payment = frappe._dict(payment) - - try: - if not data.event == 'payment.captured': - return - - # to avoid capturing subscription payments as donations - if payment.description and 'subscription' in str(payment.description).lower(): - return - - donor = get_donor(payment.email) - if not donor: - donor = create_donor(payment) - - donation = create_donation(donor, payment) - donation.run_method('create_payment_entry') - - except Exception as e: - message = '{0}\n\n{1}\n\n{2}: {3}'.format(e, frappe.get_traceback(), _('Payment ID'), payment.id) - log = frappe.log_error(message, _('Error creating donation entry for {0}').format(donor.name)) - notify_failure(log) - return { 'status': 'Failed', 'reason': e } - - return { 'status': 'Success' } - - -def create_donation(donor, payment): - if not frappe.db.exists('Mode of Payment', payment.method): - create_mode_of_payment(payment.method) - - company = get_company_for_donations() - donation = frappe.get_doc({ - 'doctype': 'Donation', - 'company': company, - 'donor': donor.name, - 'donor_name': donor.donor_name, - 'email': donor.email, - 'date': getdate(), - 'amount': flt(payment.amount) / 100, # Convert to rupees from paise - 'mode_of_payment': payment.method, - 'razorpay_payment_id': payment.id - }).insert(ignore_mandatory=True) - - donation.submit() - return donation - - -def get_donor(email): - donors = frappe.get_all('Donor', - filters={'email': email}, - order_by='creation desc') - - try: - return frappe.get_doc('Donor', donors[0]['name']) - except Exception: - return None - - -@frappe.whitelist() -def create_donor(payment): - donor_details = frappe._dict(payment) - donor_type = frappe.db.get_single_value('Non Profit Settings', 'default_donor_type') - - donor = frappe.new_doc('Donor') - donor.update({ - 'donor_name': donor_details.email, - 'donor_type': donor_type, - 'email': donor_details.email, - 'contact': donor_details.contact - }) - - if donor_details.get('notes'): - donor = get_additional_notes(donor, donor_details) - - donor.insert(ignore_mandatory=True) - return donor - - -def get_company_for_donations(): - company = frappe.db.get_single_value('Non Profit Settings', 'donation_company') - if not company: - from erpnext.non_profit.utils import get_company - company = get_company() - return company - - -def get_additional_notes(donor, donor_details): - if type(donor_details.notes) == dict: - for k, v in donor_details.notes.items(): - notes = '\n'.join('{}: {}'.format(k, v)) - - # extract donor name from notes - if 'name' in k.lower(): - donor.update({ - 'donor_name': donor_details.notes.get(k) - }) - - # extract pan from notes - if 'pan' in k.lower(): - donor.update({ - 'pan_number': donor_details.notes.get(k) - }) - - donor.add_comment('Comment', notes) - - elif type(donor_details.notes) == str: - donor.add_comment('Comment', donor_details.notes) - - return donor - - -def create_mode_of_payment(method): - frappe.get_doc({ - 'doctype': 'Mode of Payment', - 'mode_of_payment': method - }).insert(ignore_mandatory=True) - - -def notify_failure(log): - try: - content = ''' - Dear System Manager, - Razorpay webhook for creating donation failed due to some reason. - Please check the error log linked below - Error Log: {0} - Regards, Administrator - '''.format(get_link_to_form('Error Log', log.name)) - - sendmail_to_system_managers(_('[Important] [ERPNext] Razorpay donation webhook failed, please check.'), content) - except Exception: - pass diff --git a/erpnext/non_profit/doctype/donation/donation_dashboard.py b/erpnext/non_profit/doctype/donation/donation_dashboard.py deleted file mode 100644 index 492ad62171..0000000000 --- a/erpnext/non_profit/doctype/donation/donation_dashboard.py +++ /dev/null @@ -1,16 +0,0 @@ -from frappe import _ - - -def get_data(): - return { - 'fieldname': 'donation', - 'non_standard_fieldnames': { - 'Payment Entry': 'reference_name' - }, - 'transactions': [ - { - 'label': _('Payment'), - 'items': ['Payment Entry'] - } - ] - } diff --git a/erpnext/non_profit/doctype/donation/test_donation.py b/erpnext/non_profit/doctype/donation/test_donation.py deleted file mode 100644 index 5fa731a6aa..0000000000 --- a/erpnext/non_profit/doctype/donation/test_donation.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - -import frappe - -from erpnext.non_profit.doctype.donation.donation import create_donation - - -class TestDonation(unittest.TestCase): - def setUp(self): - create_donor_type() - settings = frappe.get_doc('Non Profit Settings') - settings.company = '_Test Company' - settings.donation_company = '_Test Company' - settings.default_donor_type = '_Test Donor' - settings.automate_donation_payment_entries = 1 - settings.donation_debit_account = 'Debtors - _TC' - settings.donation_payment_account = 'Cash - _TC' - settings.creation_user = 'Administrator' - settings.flags.ignore_permissions = True - settings.save() - - def test_payment_entry_for_donations(self): - donor = create_donor() - create_mode_of_payment() - payment = frappe._dict({ - 'amount': 100, - 'method': 'Debit Card', - 'id': 'pay_MeXAmsgeKOhq7O' - }) - donation = create_donation(donor, payment) - - self.assertTrue(donation.name) - - # Naive test to check if at all payment entry is generated - # This method is actually triggered from Payment Gateway - # In any case if details were missing, this would throw an error - donation.on_payment_authorized() - donation.reload() - - self.assertEqual(donation.paid, 1) - self.assertTrue(frappe.db.exists('Payment Entry', {'reference_no': donation.name})) - - -def create_donor_type(): - if not frappe.db.exists('Donor Type', '_Test Donor'): - frappe.get_doc({ - 'doctype': 'Donor Type', - 'donor_type': '_Test Donor' - }).insert() - - -def create_donor(): - donor = frappe.db.exists('Donor', 'donor@test.com') - if donor: - return frappe.get_doc('Donor', 'donor@test.com') - else: - return frappe.get_doc({ - 'doctype': 'Donor', - 'donor_name': '_Test Donor', - 'donor_type': '_Test Donor', - 'email': 'donor@test.com' - }).insert() - - -def create_mode_of_payment(): - if not frappe.db.exists('Mode of Payment', 'Debit Card'): - frappe.get_doc({ - 'doctype': 'Mode of Payment', - 'mode_of_payment': 'Debit Card', - 'accounts': [{ - 'company': '_Test Company', - 'default_account': 'Cash - _TC' - }] - }).insert() diff --git a/erpnext/non_profit/doctype/donor/__init__.py b/erpnext/non_profit/doctype/donor/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/donor/donor.js b/erpnext/non_profit/doctype/donor/donor.js deleted file mode 100644 index 090d5af32e..0000000000 --- a/erpnext/non_profit/doctype/donor/donor.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Donor', { - refresh: function(frm) { - frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Donor'}; - - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); - - if(!frm.doc.__islocal) { - frappe.contacts.render_address_and_contact(frm); - } else { - frappe.contacts.clear_address_and_contact(frm); - } - - } -}); diff --git a/erpnext/non_profit/doctype/donor/donor.json b/erpnext/non_profit/doctype/donor/donor.json deleted file mode 100644 index 72f24ef922..0000000000 --- a/erpnext/non_profit/doctype/donor/donor.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "actions": [], - "allow_rename": 1, - "autoname": "field:email", - "creation": "2017-09-19 16:20:27.510196", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "donor_name", - "column_break_5", - "donor_type", - "email", - "image", - "address_contacts", - "address_html", - "column_break_9", - "contact_html" - ], - "fields": [ - { - "fieldname": "donor_name", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Donor Name", - "reqd": 1 - }, - { - "fieldname": "column_break_5", - "fieldtype": "Column Break" - }, - { - "fieldname": "donor_type", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Donor Type", - "options": "Donor Type", - "reqd": 1 - }, - { - "fieldname": "email", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Email", - "reqd": 1, - "unique": 1 - }, - { - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "label": "Image", - "no_copy": 1, - "print_hide": 1 - }, - { - "depends_on": "eval:!doc.__islocal;", - "fieldname": "address_contacts", - "fieldtype": "Section Break", - "label": "Address and Contact", - "options": "fa fa-map-marker" - }, - { - "fieldname": "address_html", - "fieldtype": "HTML", - "label": "Address HTML" - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "fieldname": "contact_html", - "fieldtype": "HTML", - "label": "Contact HTML" - } - ], - "image_field": "image", - "links": [ - { - "link_doctype": "Donation", - "link_fieldname": "donor" - } - ], - "modified": "2021-02-17 16:36:33.470731", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Donor", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - } - ], - "quick_entry": 1, - "restrict_to_domain": "Non Profit", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "donor_name", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/donor/donor.py b/erpnext/non_profit/doctype/donor/donor.py deleted file mode 100644 index 058321b159..0000000000 --- a/erpnext/non_profit/doctype/donor/donor.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.model.document import Document - - -class Donor(Document): - def onload(self): - """Load address and contacts in `__onload`""" - load_address_and_contact(self) - - def validate(self): - from frappe.utils import validate_email_address - if self.email: - validate_email_address(self.email.strip(), True) diff --git a/erpnext/non_profit/doctype/donor/donor_list.js b/erpnext/non_profit/doctype/donor/donor_list.js deleted file mode 100644 index 31d4d292e7..0000000000 --- a/erpnext/non_profit/doctype/donor/donor_list.js +++ /dev/null @@ -1,3 +0,0 @@ -frappe.listview_settings['Donor'] = { - add_fields: ["donor_name", "donor_type", "image"], -}; diff --git a/erpnext/non_profit/doctype/donor/test_donor.py b/erpnext/non_profit/doctype/donor/test_donor.py deleted file mode 100644 index fe591c8e72..0000000000 --- a/erpnext/non_profit/doctype/donor/test_donor.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestDonor(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/donor_type/__init__.py b/erpnext/non_profit/doctype/donor_type/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.js b/erpnext/non_profit/doctype/donor_type/donor_type.js deleted file mode 100644 index 7b1fd4fe89..0000000000 --- a/erpnext/non_profit/doctype/donor_type/donor_type.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Donor Type', { - refresh: function() { - - } -}); diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.json b/erpnext/non_profit/doctype/donor_type/donor_type.json deleted file mode 100644 index 07118fdc82..0000000000 --- a/erpnext/non_profit/doctype/donor_type/donor_type.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:donor_type", - "beta": 0, - "creation": "2017-09-19 16:19:16.639635", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "donor_type", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Donor Type", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-12-05 07:04:36.757595", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Donor Type", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/donor_type/donor_type.py b/erpnext/non_profit/doctype/donor_type/donor_type.py deleted file mode 100644 index 17dca899d5..0000000000 --- a/erpnext/non_profit/doctype/donor_type/donor_type.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class DonorType(Document): - pass diff --git a/erpnext/non_profit/doctype/donor_type/test_donor_type.py b/erpnext/non_profit/doctype/donor_type/test_donor_type.py deleted file mode 100644 index d433733ee2..0000000000 --- a/erpnext/non_profit/doctype/donor_type/test_donor_type.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestDonorType(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/grant_application/__init__.py b/erpnext/non_profit/doctype/grant_application/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.js b/erpnext/non_profit/doctype/grant_application/grant_application.js deleted file mode 100644 index 70f319b828..0000000000 --- a/erpnext/non_profit/doctype/grant_application/grant_application.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Grant Application', { - refresh: function(frm) { - frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Grant Application'}; - - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); - - if(!frm.doc.__islocal) { - frappe.contacts.render_address_and_contact(frm); - } else { - frappe.contacts.clear_address_and_contact(frm); - } - - if(frm.doc.status == 'Received' && !frm.doc.email_notification_sent){ - frm.add_custom_button(__("Send Grant Review Email"), function() { - frappe.call({ - method: "erpnext.non_profit.doctype.grant_application.grant_application.send_grant_review_emails", - args: { - grant_application: frm.doc.name - } - }); - }); - } - } -}); diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.json b/erpnext/non_profit/doctype/grant_application/grant_application.json deleted file mode 100644 index 2eb2087925..0000000000 --- a/erpnext/non_profit/doctype/grant_application/grant_application.json +++ /dev/null @@ -1,851 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 1, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", - "beta": 0, - "creation": "2017-09-21 12:02:01.206913", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "applicant_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Applicant Type", - "length": 0, - "no_copy": 0, - "options": "Individual\nOrganization", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "applicant_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.applicant_type=='Organization'", - "fieldname": "contact_person", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact Person", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Email", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_5", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Open", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Open\nReceived\nIn Progress\nApproved\nRejected\nExpired\nWithdrawn", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "website_url", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Website URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_contacts", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address and Contact", - "length": 0, - "no_copy": 0, - "options": "fa fa-map-marker", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address HTML", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact HTML", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "grant_application_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Grant Application Details ", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "grant_description", - "fieldtype": "Long Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Grant Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_15", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Requested Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "has_any_past_grant_record", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Has any past Grant Record", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "route", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Route", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "published", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Show on Website", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "assessment_result", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Assessment Result", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "assessment_mark", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Assessment Mark (Out of 10)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "note", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Note", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_24", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "assessment_manager", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Assessment Manager", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email_notification_sent", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Email Notification Sent", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 1, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_field": "", - "image_view": 0, - "in_create": 0, - "is_published_field": "published", - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-12-06 12:39:57.677899", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Grant Application", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "route": "grant-application", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "applicant_name", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/grant_application/grant_application.py b/erpnext/non_profit/doctype/grant_application/grant_application.py deleted file mode 100644 index cc5e1b1442..0000000000 --- a/erpnext/non_profit/doctype/grant_application/grant_application.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ -from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.utils import get_url -from frappe.website.website_generator import WebsiteGenerator - - -class GrantApplication(WebsiteGenerator): - _website = frappe._dict( - condition_field = "published", - ) - - def validate(self): - if not self.route: #pylint: disable=E0203 - self.route = 'grant-application/' + self.scrub(self.name) - - def onload(self): - """Load address and contacts in `__onload`""" - load_address_and_contact(self) - - def get_context(self, context): - context.no_cache = True - context.show_sidebar = True - context.parents = [dict(label='View All Grant Applications', - route='grant-application', title='View Grants')] - -def get_list_context(context): - context.allow_guest = True - context.no_cache = True - context.no_breadcrumbs = True - context.show_sidebar = True - context.order_by = 'creation desc' - context.introduction =''' - Apply for new Grant Application''' - -@frappe.whitelist() -def send_grant_review_emails(grant_application): - grant = frappe.get_doc("Grant Application", grant_application) - url = get_url('grant-application/{0}'.format(grant_application)) - frappe.sendmail( - recipients= grant.assessment_manager, - sender=frappe.session.user, - subject='Grant Application for {0}'.format(grant.applicant_name), - message='

Please Review this grant application


' + url, - reference_doctype=grant.doctype, - reference_name=grant.name - ) - - grant.status = 'In Progress' - grant.email_notification_sent = 1 - grant.save() - frappe.db.commit() - - frappe.msgprint(_("Review Invitation Sent")) diff --git a/erpnext/non_profit/doctype/grant_application/templates/grant_application.html b/erpnext/non_profit/doctype/grant_application/templates/grant_application.html deleted file mode 100644 index 52e8469284..0000000000 --- a/erpnext/non_profit/doctype/grant_application/templates/grant_application.html +++ /dev/null @@ -1,68 +0,0 @@ -{% extends "templates/web.html" %} - -{% block page_content %} -

{{ applicant_name }}

- {% if frappe.user == owner %} -

Edit Grant

- {% endif %} -
- - - - - - - - - - - - - - - - - - - - - -
Organization/Indvidual{{ applicant_type }}
Grant Applicant Name{{ applicant_name}}
Date{{ frappe.format_date(creation) }}
Status{{ status }}
Email{{ email }}
-

Q. Please outline your current situation and why you are applying for a grant?

-

{{ grant_description }}

-

Q. Requested grant amount

-

{{ amount }}

-

Q. Have you recevied grant from us before?

-

{{ has_any_past_grant_record }}

-

Contact

- {% if frappe.user != 'Guest' %} - - {% if contact_person %} - - - - - {% endif %} - - - - -
Contact Person{{ contact_person }}
Email{{ email }}
- {% else %} -

You must register and login to view contact details

- {% endif %} -
- {% if frappe.session.user == assessment_manager %} - {% if assessment_scale %} -

Assessment Review done

- {% endif %} - {% else %} -


Post a New Grant

- {% endif %} -{% endblock %} -{% block style %} - - -{% endblock %} diff --git a/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html b/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html deleted file mode 100644 index e375b16154..0000000000 --- a/erpnext/non_profit/doctype/grant_application/templates/grant_application_row.html +++ /dev/null @@ -1,11 +0,0 @@ -{% if doc.published %} - -{% endif %} diff --git a/erpnext/non_profit/doctype/grant_application/test_grant_application.py b/erpnext/non_profit/doctype/grant_application/test_grant_application.py deleted file mode 100644 index ef267d7af8..0000000000 --- a/erpnext/non_profit/doctype/grant_application/test_grant_application.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestGrantApplication(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/member/__init__.py b/erpnext/non_profit/doctype/member/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/member/member.js b/erpnext/non_profit/doctype/member/member.js deleted file mode 100644 index e58ec0f5ee..0000000000 --- a/erpnext/non_profit/doctype/member/member.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Member', { - setup: function(frm) { - frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => { - if (val && (frm.doc.subscription_id || frm.doc.customer_id)) { - frm.set_df_property('razorpay_details_section', 'hidden', false); - } - }) - }, - - refresh: function(frm) { - - frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Member'}; - - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); - - if(!frm.doc.__islocal) { - frappe.contacts.render_address_and_contact(frm); - - // custom buttons - frm.add_custom_button(__('Accounting Ledger'), function() { - frappe.set_route('query-report', 'General Ledger', - {party_type:'Member', party:frm.doc.name}); - }); - - frm.add_custom_button(__('Accounts Receivable'), function() { - frappe.set_route('query-report', 'Accounts Receivable', {member:frm.doc.name}); - }); - - if (!frm.doc.customer) { - frm.add_custom_button(__('Create Customer'), () => { - frm.call('make_customer_and_link').then(() => { - frm.reload_doc(); - }); - }); - } - - // indicator - erpnext.utils.set_party_dashboard_indicators(frm); - - } else { - frappe.contacts.clear_address_and_contact(frm); - } - - frappe.call({ - method:"frappe.client.get_value", - args:{ - 'doctype':"Membership", - 'filters':{'member': frm.doc.name}, - 'fieldname':[ - 'to_date' - ] - }, - callback: function (data) { - if(data.message) { - frappe.model.set_value(frm.doctype,frm.docname, - "membership_expiry_date", data.message.to_date); - } - } - }); - } -}); diff --git a/erpnext/non_profit/doctype/member/member.json b/erpnext/non_profit/doctype/member/member.json deleted file mode 100644 index 7c1baf1a8d..0000000000 --- a/erpnext/non_profit/doctype/member/member.json +++ /dev/null @@ -1,210 +0,0 @@ -{ - "actions": [], - "allow_rename": 1, - "autoname": "naming_series:", - "creation": "2017-09-11 09:24:52.898356", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "naming_series", - "member_name", - "membership_expiry_date", - "column_break_5", - "membership_type", - "email_id", - "image", - "customer_section", - "customer", - "customer_name", - "supplier_section", - "supplier", - "address_contacts", - "address_html", - "column_break_9", - "contact_html", - "razorpay_details_section", - "subscription_id", - "customer_id", - "subscription_status", - "column_break_21", - "subscription_start", - "subscription_end" - ], - "fields": [ - { - "fieldname": "naming_series", - "fieldtype": "Select", - "label": "Series", - "options": "NPO-MEM-.YYYY.-", - "reqd": 1 - }, - { - "fieldname": "member_name", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Member Name", - "reqd": 1 - }, - { - "fieldname": "membership_expiry_date", - "fieldtype": "Date", - "label": "Membership Expiry Date" - }, - { - "fieldname": "column_break_5", - "fieldtype": "Column Break" - }, - { - "fieldname": "membership_type", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Membership Type", - "options": "Membership Type", - "reqd": 1 - }, - { - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "label": "Image", - "no_copy": 1, - "print_hide": 1 - }, - { - "collapsible": 1, - "fieldname": "customer_section", - "fieldtype": "Section Break", - "label": "Customer" - }, - { - "fieldname": "customer", - "fieldtype": "Link", - "label": "Customer", - "options": "Customer" - }, - { - "fetch_from": "customer.customer_name", - "fieldname": "customer_name", - "fieldtype": "Data", - "label": "Customer Name", - "read_only": 1 - }, - { - "collapsible": 1, - "fieldname": "supplier_section", - "fieldtype": "Section Break", - "label": "Supplier" - }, - { - "fieldname": "supplier", - "fieldtype": "Link", - "label": "Supplier", - "options": "Supplier" - }, - { - "depends_on": "eval:!doc.__islocal;", - "fieldname": "address_contacts", - "fieldtype": "Section Break", - "label": "Address and Contact", - "options": "fa fa-map-marker" - }, - { - "fieldname": "address_html", - "fieldtype": "HTML", - "label": "Address HTML" - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "fieldname": "contact_html", - "fieldtype": "HTML", - "label": "Contact HTML" - }, - { - "fieldname": "email_id", - "fieldtype": "Data", - "label": "Email Address", - "options": "Email" - }, - { - "fieldname": "subscription_id", - "fieldtype": "Data", - "label": "Subscription ID", - "read_only": 1 - }, - { - "fieldname": "customer_id", - "fieldtype": "Data", - "label": "Customer ID", - "read_only": 1 - }, - { - "fieldname": "razorpay_details_section", - "fieldtype": "Section Break", - "hidden": 1, - "label": "Razorpay Details" - }, - { - "fieldname": "column_break_21", - "fieldtype": "Column Break" - }, - { - "fieldname": "subscription_start", - "fieldtype": "Date", - "label": "Subscription Start " - }, - { - "fieldname": "subscription_end", - "fieldtype": "Date", - "label": "Subscription End" - }, - { - "fieldname": "subscription_status", - "fieldtype": "Select", - "label": "Subscription Status", - "options": "\nActive\nHalted" - } - ], - "image_field": "image", - "links": [], - "modified": "2021-07-11 14:27:26.368039", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Member", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Member", - "share": 1, - "write": 1 - } - ], - "quick_entry": 1, - "restrict_to_domain": "Non Profit", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "member_name", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py deleted file mode 100644 index 4d80e57ecc..0000000000 --- a/erpnext/non_profit/doctype/member/member.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ -from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.integrations.utils import get_payment_gateway_controller -from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form - -from erpnext.non_profit.doctype.membership_type.membership_type import get_membership_type - - -class Member(Document): - def onload(self): - """Load address and contacts in `__onload`""" - load_address_and_contact(self) - - - def validate(self): - if self.email_id: - self.validate_email_type(self.email_id) - - def validate_email_type(self, email): - from frappe.utils import validate_email_address - validate_email_address(email.strip(), True) - - def setup_subscription(self): - non_profit_settings = frappe.get_doc('Non Profit Settings') - if not non_profit_settings.enable_razorpay_for_memberships: - frappe.throw(_('Please check Enable Razorpay for Memberships in {0} to setup subscription')).format( - get_link_to_form('Non Profit Settings', 'Non Profit Settings')) - - controller = get_payment_gateway_controller("Razorpay") - settings = controller.get_settings({}) - - plan_id = frappe.get_value("Membership Type", self.membership_type, "razorpay_plan_id") - - if not plan_id: - frappe.throw(_("Please setup Razorpay Plan ID")) - - subscription_details = { - "plan_id": plan_id, - "billing_frequency": cint(non_profit_settings.billing_frequency), - "customer_notify": 1 - } - - args = { - 'subscription_details': subscription_details - } - - subscription = controller.setup_subscription(settings, **args) - - return subscription - - @frappe.whitelist() - def make_customer_and_link(self): - if self.customer: - frappe.msgprint(_("A customer is already linked to this Member")) - - customer = create_customer(frappe._dict({ - 'fullname': self.member_name, - 'email': self.email_id, - 'phone': None - })) - - self.customer = customer - self.save() - frappe.msgprint(_("Customer {0} has been created succesfully.").format(self.customer)) - - -def get_or_create_member(user_details): - member_list = frappe.get_all("Member", filters={'email': user_details.email, 'membership_type': user_details.plan_id}) - if member_list and member_list[0]: - return member_list[0]['name'] - else: - return create_member(user_details) - -def create_member(user_details): - user_details = frappe._dict(user_details) - member = frappe.new_doc("Member") - member.update({ - "member_name": user_details.fullname, - "email_id": user_details.email, - "pan_number": user_details.pan or None, - "membership_type": user_details.plan_id, - "customer_id": user_details.customer_id or None, - "subscription_id": user_details.subscription_id or None, - "subscription_status": user_details.subscription_status or "" - }) - - member.insert(ignore_permissions=True) - member.customer = create_customer(user_details, member.name) - member.save(ignore_permissions=True) - - return member - -def create_customer(user_details, member=None): - customer = frappe.new_doc("Customer") - customer.customer_name = user_details.fullname - customer.customer_type = "Individual" - customer.flags.ignore_mandatory = True - customer.insert(ignore_permissions=True) - - try: - contact = frappe.new_doc("Contact") - contact.first_name = user_details.fullname - if user_details.mobile: - contact.add_phone(user_details.mobile, is_primary_phone=1, is_primary_mobile_no=1) - if user_details.email: - contact.add_email(user_details.email, is_primary=1) - contact.insert(ignore_permissions=True) - - contact.append("links", { - "link_doctype": "Customer", - "link_name": customer.name - }) - - if member: - contact.append("links", { - "link_doctype": "Member", - "link_name": member - }) - - contact.save(ignore_permissions=True) - - except frappe.DuplicateEntryError: - return customer.name - - except Exception as e: - frappe.log_error(frappe.get_traceback(), _("Contact Creation Failed")) - pass - - return customer.name - -@frappe.whitelist(allow_guest=True) -def create_member_subscription_order(user_details): - """Create Member subscription and order for payment - - Args: - user_details (TYPE): Description - - Returns: - Dictionary: Dictionary with subscription details - { - 'subscription_details': { - 'plan_id': 'plan_EXwyxDYDCj3X4v', - 'billing_frequency': 24, - 'customer_notify': 1 - }, - 'subscription_id': 'sub_EZycCvXFvqnC6p' - } - """ - - user_details = frappe._dict(user_details) - member = get_or_create_member(user_details) - - subscription = member.setup_subscription() - - member.subscription_id = subscription.get('subscription_id') - member.save(ignore_permissions=True) - - return subscription - -@frappe.whitelist() -def register_member(fullname, email, rzpay_plan_id, subscription_id, pan=None, mobile=None): - plan = get_membership_type(rzpay_plan_id) - if not plan: - raise frappe.DoesNotExistError - - member = frappe.db.exists("Member", {'email': email, 'subscription_id': subscription_id }) - if member: - return member - else: - member = create_member(dict( - fullname=fullname, - email=email, - plan_id=plan, - subscription_id=subscription_id, - pan=pan, - mobile=mobile - )) - - return member.name diff --git a/erpnext/non_profit/doctype/member/member_dashboard.py b/erpnext/non_profit/doctype/member/member_dashboard.py deleted file mode 100644 index 0e31e3ceb8..0000000000 --- a/erpnext/non_profit/doctype/member/member_dashboard.py +++ /dev/null @@ -1,22 +0,0 @@ -from frappe import _ - - -def get_data(): - return { - 'heatmap': True, - 'heatmap_message': _('Member Activity'), - 'fieldname': 'member', - 'non_standard_fieldnames': { - 'Bank Account': 'party' - }, - 'transactions': [ - { - 'label': _('Membership Details'), - 'items': ['Membership'] - }, - { - 'label': _('Fee'), - 'items': ['Bank Account'] - } - ] - } diff --git a/erpnext/non_profit/doctype/member/member_list.js b/erpnext/non_profit/doctype/member/member_list.js deleted file mode 100644 index 8e41e7fdde..0000000000 --- a/erpnext/non_profit/doctype/member/member_list.js +++ /dev/null @@ -1,3 +0,0 @@ -frappe.listview_settings['Member'] = { - add_fields: ["member_name", "membership_type", "image"], -}; diff --git a/erpnext/non_profit/doctype/member/test_member.py b/erpnext/non_profit/doctype/member/test_member.py deleted file mode 100644 index 46f14ed131..0000000000 --- a/erpnext/non_profit/doctype/member/test_member.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestMember(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/membership/__init__.py b/erpnext/non_profit/doctype/membership/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/membership/membership.js b/erpnext/non_profit/doctype/membership/membership.js deleted file mode 100644 index 31872048a0..0000000000 --- a/erpnext/non_profit/doctype/membership/membership.js +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Membership', { - setup: function(frm) { - frappe.db.get_single_value("Non Profit Settings", "enable_razorpay_for_memberships").then(val => { - if (val) frm.set_df_property("razorpay_details_section", "hidden", false); - }) - }, - - refresh: function(frm) { - if (frm.doc.__islocal) - return; - - !frm.doc.invoice && frm.add_custom_button("Generate Invoice", () => { - frm.call({ - doc: frm.doc, - method: "generate_invoice", - args: {save: true}, - freeze: true, - freeze_message: __("Creating Membership Invoice"), - callback: function(r) { - if (r.invoice) - frm.reload_doc(); - } - }); - }); - - frappe.db.get_single_value("Non Profit Settings", "send_email").then(val => { - if (val) frm.add_custom_button("Send Acknowledgement", () => { - frm.call("send_acknowlement").then(() => { - frm.reload_doc(); - }); - }); - }) - }, - - onload: function(frm) { - frm.add_fetch("membership_type", "amount", "amount"); - } -}); diff --git a/erpnext/non_profit/doctype/membership/membership.json b/erpnext/non_profit/doctype/membership/membership.json deleted file mode 100644 index 11d32f9c2b..0000000000 --- a/erpnext/non_profit/doctype/membership/membership.json +++ /dev/null @@ -1,184 +0,0 @@ -{ - "actions": [], - "autoname": "NPO-MSH-.YYYY.-.#####", - "creation": "2017-09-11 11:39:18.492184", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "member", - "member_name", - "membership_type", - "column_break_3", - "company", - "membership_status", - "membership_validity_section", - "from_date", - "to_date", - "column_break_8", - "member_since_date", - "payment_details", - "paid", - "currency", - "amount", - "invoice", - "razorpay_details_section", - "subscription_id", - "payment_id" - ], - "fields": [ - { - "fieldname": "member", - "fieldtype": "Link", - "label": "Member", - "options": "Member" - }, - { - "fieldname": "membership_type", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Membership Type", - "options": "Membership Type", - "reqd": 1 - }, - { - "fieldname": "column_break_3", - "fieldtype": "Column Break" - }, - { - "fieldname": "membership_status", - "fieldtype": "Select", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Membership Status", - "options": "New\nCurrent\nExpired\nPending\nCancelled" - }, - { - "fieldname": "membership_validity_section", - "fieldtype": "Section Break", - "label": "Validity" - }, - { - "fieldname": "from_date", - "fieldtype": "Date", - "in_list_view": 1, - "label": "From", - "reqd": 1 - }, - { - "fieldname": "to_date", - "fieldtype": "Date", - "in_list_view": 1, - "label": "To", - "reqd": 1 - }, - { - "fieldname": "column_break_8", - "fieldtype": "Column Break" - }, - { - "fieldname": "member_since_date", - "fieldtype": "Date", - "label": "Member Since" - }, - { - "fieldname": "payment_details", - "fieldtype": "Section Break", - "label": "Payment Details" - }, - { - "default": "0", - "fieldname": "paid", - "fieldtype": "Check", - "label": "Paid" - }, - { - "fieldname": "currency", - "fieldtype": "Link", - "label": "Currency", - "options": "Currency" - }, - { - "fieldname": "amount", - "fieldtype": "Float", - "label": "Amount" - }, - { - "fieldname": "razorpay_details_section", - "fieldtype": "Section Break", - "hidden": 1, - "label": "Razorpay Details" - }, - { - "fieldname": "subscription_id", - "fieldtype": "Data", - "label": "Subscription ID", - "read_only": 1 - }, - { - "fieldname": "payment_id", - "fieldtype": "Data", - "label": "Payment ID", - "read_only": 1 - }, - { - "fieldname": "invoice", - "fieldtype": "Link", - "label": "Invoice", - "options": "Sales Invoice" - }, - { - "fetch_from": "member.member_name", - "fieldname": "member_name", - "fieldtype": "Data", - "label": "Member Name", - "read_only": 1 - }, - { - "fieldname": "company", - "fieldtype": "Link", - "label": "Company", - "options": "Company", - "reqd": 1 - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-02-19 14:33:44.925122", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Membership", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Member", - "share": 1, - "write": 1 - } - ], - "restrict_to_domain": "Non Profit", - "search_fields": "member, member_name", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "member_name", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py deleted file mode 100644 index f9b295a223..0000000000 --- a/erpnext/non_profit/doctype/membership/membership.py +++ /dev/null @@ -1,415 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import json -from datetime import datetime - -import frappe -from frappe import _ -from frappe.email import sendmail_to_system_managers -from frappe.model.document import Document -from frappe.utils import add_days, add_months, add_years, get_link_to_form, getdate, nowdate - -import erpnext -from erpnext.non_profit.doctype.member.member import create_member - - -class Membership(Document): - def validate(self): - if not self.member or not frappe.db.exists("Member", self.member): - # for web forms - user_type = frappe.db.get_value("User", frappe.session.user, "user_type") - if user_type == "Website User": - self.create_member_from_website_user() - else: - frappe.throw(_("Please select a Member")) - - self.validate_membership_period() - - def create_member_from_website_user(self): - member_name = frappe.get_value("Member", dict(email_id=frappe.session.user)) - - if not member_name: - user = frappe.get_doc("User", frappe.session.user) - member = frappe.get_doc(dict( - doctype="Member", - email_id=frappe.session.user, - membership_type=self.membership_type, - member_name=user.get_fullname() - )).insert(ignore_permissions=True) - member_name = member.name - - if self.get("__islocal"): - self.member = member_name - - def validate_membership_period(self): - # get last membership (if active) - last_membership = erpnext.get_last_membership(self.member) - - # if person applied for offline membership - if last_membership and last_membership.name != self.name and not frappe.session.user == "Administrator": - # if last membership does not expire in 30 days, then do not allow to renew - if getdate(add_days(last_membership.to_date, -30)) > getdate(nowdate()) : - frappe.throw(_("You can only renew if your membership expires within 30 days")) - - self.from_date = add_days(last_membership.to_date, 1) - elif frappe.session.user == "Administrator": - self.from_date = self.from_date - else: - self.from_date = nowdate() - - if frappe.db.get_single_value("Non Profit Settings", "billing_cycle") == "Yearly": - self.to_date = add_years(self.from_date, 1) - else: - self.to_date = add_months(self.from_date, 1) - - def on_payment_authorized(self, status_changed_to=None): - if status_changed_to not in ("Completed", "Authorized"): - return - self.load_from_db() - self.db_set("paid", 1) - settings = frappe.get_doc("Non Profit Settings") - if settings.allow_invoicing and settings.automate_membership_invoicing: - self.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True) - - - @frappe.whitelist() - def generate_invoice(self, save=True, with_payment_entry=False): - if not (self.paid or self.currency or self.amount): - frappe.throw(_("The payment for this membership is not paid. To generate invoice fill the payment details")) - - if self.invoice: - frappe.throw(_("An invoice is already linked to this document")) - - member = frappe.get_doc("Member", self.member) - if not member.customer: - frappe.throw(_("No customer linked to member {0}").format(frappe.bold(self.member))) - - plan = frappe.get_doc("Membership Type", self.membership_type) - settings = frappe.get_doc("Non Profit Settings") - self.validate_membership_type_and_settings(plan, settings) - - invoice = make_invoice(self, member, plan, settings) - self.reload() - self.invoice = invoice.name - - if with_payment_entry: - self.make_payment_entry(settings, invoice) - - if save: - self.save() - - return invoice - - def validate_membership_type_and_settings(self, plan, settings): - settings_link = get_link_to_form("Membership Type", self.membership_type) - - if not settings.membership_debit_account: - frappe.throw(_("You need to set Debit Account in {0}").format(settings_link)) - - if not settings.company: - frappe.throw(_("You need to set Default Company for invoicing in {0}").format(settings_link)) - - if not plan.linked_item: - frappe.throw(_("Please set a Linked Item for the Membership Type {0}").format( - get_link_to_form("Membership Type", self.membership_type))) - - def make_payment_entry(self, settings, invoice): - if not settings.membership_payment_account: - frappe.throw(_("You need to set Payment Account for Membership in {0}").format( - get_link_to_form("Non Profit Settings", "Non Profit Settings"))) - - from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry - frappe.flags.ignore_account_permission = True - pe = get_payment_entry(dt="Sales Invoice", dn=invoice.name, bank_amount=invoice.grand_total) - frappe.flags.ignore_account_permission=False - pe.paid_to = settings.membership_payment_account - pe.reference_no = self.name - pe.reference_date = getdate() - pe.flags.ignore_mandatory = True - pe.save() - pe.submit() - - @frappe.whitelist() - def send_acknowlement(self): - settings = frappe.get_doc("Non Profit Settings") - if not settings.send_email: - frappe.throw(_("You need to enable Send Acknowledge Email in {0}").format( - get_link_to_form("Non Profit Settings", "Non Profit Settings"))) - - member = frappe.get_doc("Member", self.member) - if not member.email_id: - frappe.throw(_("Email address of member {0} is missing").format(frappe.utils.get_link_to_form("Member", self.member))) - - plan = frappe.get_doc("Membership Type", self.membership_type) - email = member.email_id - attachments = [frappe.attach_print("Membership", self.name, print_format=settings.membership_print_format)] - - if self.invoice and settings.send_invoice: - attachments.append(frappe.attach_print("Sales Invoice", self.invoice, print_format=settings.inv_print_format)) - - email_template = frappe.get_doc("Email Template", settings.email_template) - context = { "doc": self, "member": member} - - email_args = { - "recipients": [email], - "message": frappe.render_template(email_template.get("response"), context), - "subject": frappe.render_template(email_template.get("subject"), context), - "attachments": attachments, - "reference_doctype": self.doctype, - "reference_name": self.name - } - - if not frappe.flags.in_test: - frappe.enqueue(method=frappe.sendmail, queue="short", timeout=300, is_async=True, **email_args) - else: - frappe.sendmail(**email_args) - - def generate_and_send_invoice(self): - self.generate_invoice(save=False) - self.send_acknowlement() - - -def make_invoice(membership, member, plan, settings): - invoice = frappe.get_doc({ - "doctype": "Sales Invoice", - "customer": member.customer, - "debit_to": settings.membership_debit_account, - "currency": membership.currency, - "company": settings.company, - "is_pos": 0, - "items": [ - { - "item_code": plan.linked_item, - "rate": membership.amount, - "qty": 1 - } - ] - }) - invoice.set_missing_values() - invoice.insert() - invoice.submit() - - frappe.msgprint(_("Sales Invoice created successfully")) - - return invoice - - -def get_member_based_on_subscription(subscription_id, email=None, customer_id=None): - filters = {"subscription_id": subscription_id} - if email: - filters.update({"email_id": email}) - if customer_id: - filters.update({"customer_id": customer_id}) - - members = frappe.get_all("Member", filters=filters, order_by="creation desc") - - try: - return frappe.get_doc("Member", members[0]["name"]) - except Exception: - return None - - -def verify_signature(data, endpoint="Membership"): - signature = frappe.request.headers.get("X-Razorpay-Signature") - - settings = frappe.get_doc("Non Profit Settings") - key = settings.get_webhook_secret(endpoint) - - controller = frappe.get_doc("Razorpay Settings") - - controller.verify_signature(data, signature, key) - frappe.set_user(settings.creation_user) - - -@frappe.whitelist(allow_guest=True) -def trigger_razorpay_subscription(*args, **kwargs): - data = frappe.request.get_data(as_text=True) - data = process_request_data(data) - - subscription = data.payload.get("subscription", {}).get("entity", {}) - subscription = frappe._dict(subscription) - - payment = data.payload.get("payment", {}).get("entity", {}) - payment = frappe._dict(payment) - - try: - if not data.event == "subscription.charged": - return - - member = get_member_based_on_subscription(subscription.id, payment.email) - if not member: - member = create_member(frappe._dict({ - "fullname": payment.email, - "email": payment.email, - "plan_id": get_plan_from_razorpay_id(subscription.plan_id) - })) - - member.subscription_id = subscription.id - member.customer_id = payment.customer_id - - if subscription.get("notes"): - member = get_additional_notes(member, subscription) - - company = get_company_for_memberships() - # Update Membership - membership = frappe.new_doc("Membership") - membership.update({ - "company": company, - "member": member.name, - "membership_status": "Current", - "membership_type": member.membership_type, - "currency": "INR", - "paid": 1, - "payment_id": payment.id, - "from_date": datetime.fromtimestamp(subscription.current_start), - "to_date": datetime.fromtimestamp(subscription.current_end), - "amount": payment.amount / 100 # Convert to rupees from paise - }) - membership.flags.ignore_mandatory = True - membership.insert() - - # Update membership values - member.subscription_start = datetime.fromtimestamp(subscription.start_at) - member.subscription_end = datetime.fromtimestamp(subscription.end_at) - member.subscription_status = "Active" - member.flags.ignore_mandatory = True - member.save() - - settings = frappe.get_doc("Non Profit Settings") - if settings.allow_invoicing and settings.automate_membership_invoicing: - membership.reload() - membership.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True) - - except Exception as e: - message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), _("Payment ID"), payment.id) - log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name)) - notify_failure(log) - return {"status": "Failed", "reason": e} - - return {"status": "Success"} - - -@frappe.whitelist(allow_guest=True) -def update_halted_razorpay_subscription(*args, **kwargs): - """ - When all retries have been exhausted, Razorpay moves the subscription to the halted state. - The customer has to manually retry the charge or change the card linked to the subscription, - for the subscription to move back to the active state. - """ - if frappe.request: - data = frappe.request.get_data(as_text=True) - data = process_request_data(data) - elif frappe.flags.in_test: - data = kwargs.get("data") - data = frappe._dict(data) - else: - return - - if not data.event == "subscription.halted": - return - - subscription = data.payload.get("subscription", {}).get("entity", {}) - subscription = frappe._dict(subscription) - - try: - member = get_member_based_on_subscription(subscription.id, customer_id=subscription.customer_id) - if not member: - frappe.throw(_("Member with Razorpay Subscription ID {0} not found").format(subscription.id)) - - member.subscription_status = "Halted" - member.flags.ignore_mandatory = True - member.save() - - if subscription.get("notes"): - member = get_additional_notes(member, subscription) - - except Exception as e: - message = "{0}\n\n{1}".format(e, frappe.get_traceback()) - log = frappe.log_error(message, _("Error updating halted status for member {0}").format(member.name)) - notify_failure(log) - return {"status": "Failed", "reason": e} - - return {"status": "Success"} - - -def process_request_data(data): - try: - verify_signature(data) - except Exception as e: - log = frappe.log_error(e, "Membership Webhook Verification Error") - notify_failure(log) - return {"status": "Failed", "reason": e} - - if isinstance(data, str): - data = json.loads(data) - data = frappe._dict(data) - - return data - - -def get_company_for_memberships(): - company = frappe.db.get_single_value("Non Profit Settings", "company") - if not company: - from erpnext.non_profit.utils import get_company - company = get_company() - return company - - -def get_additional_notes(member, subscription): - if type(subscription.notes) == dict: - for k, v in subscription.notes.items(): - notes = "\n".join("{}: {}".format(k, v)) - - # extract member name from notes - if "name" in k.lower(): - member.update({ - "member_name": subscription.notes.get(k) - }) - - # extract pan number from notes - if "pan" in k.lower(): - member.update({ - "pan_number": subscription.notes.get(k) - }) - - member.add_comment("Comment", notes) - - elif type(subscription.notes) == str: - member.add_comment("Comment", subscription.notes) - - return member - - -def notify_failure(log): - try: - content = """ - Dear System Manager, - Razorpay webhook for creating renewing membership subscription failed due to some reason. - Please check the following error log linked below - Error Log: {0} - Regards, Administrator - """.format(get_link_to_form("Error Log", log.name)) - - sendmail_to_system_managers("[Important] [ERPNext] Razorpay membership webhook failed , please check.", content) - except Exception: - pass - - -def get_plan_from_razorpay_id(plan_id): - plan = frappe.get_all("Membership Type", filters={"razorpay_plan_id": plan_id}, order_by="creation desc") - - try: - return plan[0]["name"] - except Exception: - return None - - -def set_expired_status(): - frappe.db.sql(""" - UPDATE - `tabMembership` SET `membership_status` = 'Expired' - WHERE - `membership_status` not in ('Cancelled') AND `to_date` < %s - """, (nowdate())) diff --git a/erpnext/non_profit/doctype/membership/membership_list.js b/erpnext/non_profit/doctype/membership/membership_list.js deleted file mode 100644 index a959159899..0000000000 --- a/erpnext/non_profit/doctype/membership/membership_list.js +++ /dev/null @@ -1,15 +0,0 @@ -frappe.listview_settings['Membership'] = { - get_indicator: function(doc) { - if (doc.membership_status == 'New') { - return [__('New'), 'blue', 'membership_status,=,New']; - } else if (doc.membership_status === 'Current') { - return [__('Current'), 'green', 'membership_status,=,Current']; - } else if (doc.membership_status === 'Pending') { - return [__('Pending'), 'yellow', 'membership_status,=,Pending']; - } else if (doc.membership_status === 'Expired') { - return [__('Expired'), 'grey', 'membership_status,=,Expired']; - } else { - return [__('Cancelled'), 'red', 'membership_status,=,Cancelled']; - } - } -}; diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py deleted file mode 100644 index fbe344c6a1..0000000000 --- a/erpnext/non_profit/doctype/membership/test_membership.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - -import frappe -from frappe.utils import add_months, nowdate - -import erpnext -from erpnext.non_profit.doctype.member.member import create_member -from erpnext.non_profit.doctype.membership.membership import update_halted_razorpay_subscription - - -class TestMembership(unittest.TestCase): - def setUp(self): - plan = setup_membership() - - # make test member - self.member_doc = create_member( - frappe._dict({ - "fullname": "_Test_Member", - "email": "_test_member_erpnext@example.com", - "plan_id": plan.name, - "subscription_id": "sub_DEX6xcJ1HSW4CR", - "customer_id": "cust_C0WlbKhp3aLA7W", - "subscription_status": "Active" - }) - ) - self.member_doc.make_customer_and_link() - self.member = self.member_doc.name - - def test_auto_generate_invoice_and_payment_entry(self): - entry = make_membership(self.member) - - # Naive test to see if at all invoice was generated and attached to member - # In any case if details were missing, the invoicing would throw an error - invoice = entry.generate_invoice(save=True) - self.assertEqual(invoice.name, entry.invoice) - - def test_renew_within_30_days(self): - # create a membership for two months - # Should work fine - make_membership(self.member, { "from_date": nowdate() }) - make_membership(self.member, { "from_date": add_months(nowdate(), 1) }) - - from frappe.utils.user import add_role - add_role("test@example.com", "Non Profit Manager") - frappe.set_user("test@example.com") - - # create next membership with expiry not within 30 days - self.assertRaises(frappe.ValidationError, make_membership, self.member, { - "from_date": add_months(nowdate(), 2), - }) - - frappe.set_user("Administrator") - # create the same membership but as administrator - make_membership(self.member, { - "from_date": add_months(nowdate(), 2), - "to_date": add_months(nowdate(), 3), - }) - - def test_halted_memberships(self): - make_membership(self.member, { - "from_date": add_months(nowdate(), 2), - "to_date": add_months(nowdate(), 3) - }) - - self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Active") - payload = get_subscription_payload() - update_halted_razorpay_subscription(data=payload) - self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Halted") - - def tearDown(self): - frappe.db.rollback() - -def set_config(key, value): - frappe.db.set_value("Non Profit Settings", None, key, value) - -def make_membership(member, payload={}): - data = { - "doctype": "Membership", - "member": member, - "membership_status": "Current", - "membership_type": "_rzpy_test_milythm", - "currency": "INR", - "paid": 1, - "from_date": nowdate(), - "amount": 100 - } - data.update(payload) - membership = frappe.get_doc(data) - membership.insert(ignore_permissions=True, ignore_if_duplicate=True) - return membership - -def create_item(item_code): - if not frappe.db.exists("Item", item_code): - item = frappe.new_doc("Item") - item.item_code = item_code - item.item_name = item_code - item.stock_uom = "Nos" - item.description = item_code - item.item_group = "All Item Groups" - item.is_stock_item = 0 - item.save() - else: - item = frappe.get_doc("Item", item_code) - return item - -def setup_membership(): - # Get default company - company = frappe.get_doc("Company", erpnext.get_default_company()) - - # update non profit settings - settings = frappe.get_doc("Non Profit Settings") - # Enable razorpay - settings.enable_razorpay_for_memberships = 1 - settings.billing_cycle = "Monthly" - settings.billing_frequency = 24 - # Enable invoicing - settings.allow_invoicing = 1 - settings.automate_membership_payment_entries = 1 - settings.company = company.name - settings.donation_company = company.name - settings.membership_payment_account = company.default_cash_account - settings.membership_debit_account = company.default_receivable_account - settings.flags.ignore_mandatory = True - settings.save() - - # make test plan - if not frappe.db.exists("Membership Type", "_rzpy_test_milythm"): - plan = frappe.new_doc("Membership Type") - plan.membership_type = "_rzpy_test_milythm" - plan.amount = 100 - plan.razorpay_plan_id = "_rzpy_test_milythm" - plan.linked_item = create_item("_Test Item for Non Profit Membership").name - plan.insert() - else: - plan = frappe.get_doc("Membership Type", "_rzpy_test_milythm") - - return plan - -def get_subscription_payload(): - return { - "entity": "event", - "account_id": "acc_BFQ7uQEaa7j2z7", - "event": "subscription.halted", - "contains": [ - "subscription" - ], - "payload": { - "subscription": { - "entity": { - "id": "sub_DEX6xcJ1HSW4CR", - "entity": "subscription", - "plan_id": "_rzpy_test_milythm", - "customer_id": "cust_C0WlbKhp3aLA7W", - "status": "halted", - "notes": { - "Important": "Notes for Internal Reference" - }, - } - } - } - } diff --git a/erpnext/non_profit/doctype/membership_type/__init__.py b/erpnext/non_profit/doctype/membership_type/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.js b/erpnext/non_profit/doctype/membership_type/membership_type.js deleted file mode 100644 index 2f2427629c..0000000000 --- a/erpnext/non_profit/doctype/membership_type/membership_type.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Membership Type', { - refresh: function (frm) { - frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => { - if (val) frm.set_df_property('razorpay_plan_id', 'hidden', false); - }); - - frappe.db.get_single_value('Non Profit Settings', 'allow_invoicing').then(val => { - if (val) frm.set_df_property('linked_item', 'hidden', false); - }); - - frm.set_query('linked_item', () => { - return { - filters: { - is_stock_item: 0 - } - }; - }); - } -}); diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.json b/erpnext/non_profit/doctype/membership_type/membership_type.json deleted file mode 100644 index 6ce1ecde12..0000000000 --- a/erpnext/non_profit/doctype/membership_type/membership_type.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "actions": [], - "autoname": "field:membership_type", - "creation": "2017-09-18 12:56:56.343999", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "membership_type", - "amount", - "razorpay_plan_id", - "linked_item" - ], - "fields": [ - { - "fieldname": "membership_type", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Membership Type", - "reqd": 1, - "unique": 1 - }, - { - "fieldname": "amount", - "fieldtype": "Float", - "in_list_view": 1, - "label": "Amount", - "reqd": 1 - }, - { - "fieldname": "razorpay_plan_id", - "fieldtype": "Data", - "hidden": 1, - "label": "Razorpay Plan ID", - "unique": 1 - }, - { - "fieldname": "linked_item", - "fieldtype": "Link", - "label": "Linked Item", - "options": "Item", - "unique": 1 - } - ], - "links": [], - "modified": "2020-08-05 15:21:43.595745", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Membership Type", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - } - ], - "quick_entry": 1, - "restrict_to_domain": "Non Profit", - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.py b/erpnext/non_profit/doctype/membership_type/membership_type.py deleted file mode 100644 index b446421571..0000000000 --- a/erpnext/non_profit/doctype/membership_type/membership_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ -from frappe.model.document import Document - - -class MembershipType(Document): - def validate(self): - if self.linked_item: - is_stock_item = frappe.db.get_value("Item", self.linked_item, "is_stock_item") - if is_stock_item: - frappe.throw(_("The Linked Item should be a service item")) - -def get_membership_type(razorpay_id): - return frappe.db.exists("Membership Type", {"razorpay_plan_id": razorpay_id}) diff --git a/erpnext/non_profit/doctype/membership_type/test_membership_type.py b/erpnext/non_profit/doctype/membership_type/test_membership_type.py deleted file mode 100644 index 98bc087acd..0000000000 --- a/erpnext/non_profit/doctype/membership_type/test_membership_type.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestMembershipType(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/non_profit_settings/__init__.py b/erpnext/non_profit/doctype/non_profit_settings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js deleted file mode 100644 index 4c4ca9834b..0000000000 --- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on("Non Profit Settings", { - refresh: function(frm) { - frm.set_query("inv_print_format", function() { - return { - filters: { - "doc_type": "Sales Invoice" - } - }; - }); - - frm.set_query("membership_print_format", function() { - return { - filters: { - "doc_type": "Membership" - } - }; - }); - - frm.set_query("membership_debit_account", function() { - return { - filters: { - "account_type": "Receivable", - "is_group": 0, - "company": frm.doc.company - } - }; - }); - - frm.set_query("donation_debit_account", function() { - return { - filters: { - "account_type": "Receivable", - "is_group": 0, - "company": frm.doc.donation_company - } - }; - }); - - frm.set_query("membership_payment_account", function () { - var account_types = ["Bank", "Cash"]; - return { - filters: { - "account_type": ["in", account_types], - "is_group": 0, - "company": frm.doc.company - } - }; - }); - - frm.set_query("donation_payment_account", function () { - var account_types = ["Bank", "Cash"]; - return { - filters: { - "account_type": ["in", account_types], - "is_group": 0, - "company": frm.doc.donation_company - } - }; - }); - - let docs_url = "https://docs.erpnext.com/docs/user/manual/en/non_profit/membership"; - - frm.set_intro(__("You can learn more about memberships in the manual. ") + `${__('ERPNext Docs')}`, true); - frm.trigger("setup_buttons_for_membership"); - frm.trigger("setup_buttons_for_donation"); - }, - - setup_buttons_for_membership: function(frm) { - let label; - - if (frm.doc.membership_webhook_secret) { - - frm.add_custom_button(__("Copy Webhook URL"), () => { - frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.membership.membership.trigger_razorpay_subscription`); - }, __("Memberships")); - - frm.add_custom_button(__("Revoke Key"), () => { - frm.call("revoke_key", { - key: "membership_webhook_secret" - }).then(() => { - frm.refresh(); - }); - }, __("Memberships")); - - label = __("Regenerate Webhook Secret"); - - } else { - label = __("Generate Webhook Secret"); - } - - frm.add_custom_button(label, () => { - frm.call("generate_webhook_secret", { - field: "membership_webhook_secret" - }).then(() => { - frm.refresh(); - }); - }, __("Memberships")); - }, - - setup_buttons_for_donation: function(frm) { - let label; - - if (frm.doc.donation_webhook_secret) { - label = __("Regenerate Webhook Secret"); - - frm.add_custom_button(__("Copy Webhook URL"), () => { - frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.donation.donation.capture_razorpay_donations`); - }, __("Donations")); - - frm.add_custom_button(__("Revoke Key"), () => { - frm.call("revoke_key", { - key: "donation_webhook_secret" - }).then(() => { - frm.refresh(); - }); - }, __("Donations")); - - } else { - label = __("Generate Webhook Secret"); - } - - frm.add_custom_button(label, () => { - frm.call("generate_webhook_secret", { - field: "donation_webhook_secret" - }).then(() => { - frm.refresh(); - }); - }, __("Donations")); - } -}); diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json deleted file mode 100644 index 25ff0c1bb0..0000000000 --- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "actions": [], - "creation": "2020-03-29 12:57:03.005120", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "enable_razorpay_for_memberships", - "razorpay_settings_section", - "billing_cycle", - "billing_frequency", - "membership_webhook_secret", - "column_break_6", - "allow_invoicing", - "automate_membership_invoicing", - "automate_membership_payment_entries", - "company", - "membership_debit_account", - "membership_payment_account", - "column_break_9", - "send_email", - "send_invoice", - "membership_print_format", - "inv_print_format", - "email_template", - "donation_settings_section", - "donation_company", - "default_donor_type", - "donation_webhook_secret", - "column_break_22", - "automate_donation_payment_entries", - "donation_debit_account", - "donation_payment_account", - "section_break_27", - "creation_user" - ], - "fields": [ - { - "fieldname": "billing_cycle", - "fieldtype": "Select", - "label": "Billing Cycle", - "options": "Monthly\nYearly" - }, - { - "depends_on": "eval:doc.enable_razorpay_for_memberships", - "fieldname": "razorpay_settings_section", - "fieldtype": "Section Break", - "label": "RazorPay Settings for Memberships" - }, - { - "description": "The number of billing cycles for which the customer should be charged. For example, if a customer is buying a 1-year membership that should be billed on a monthly basis, this value should be 12.", - "fieldname": "billing_frequency", - "fieldtype": "Int", - "label": "Billing Frequency" - }, - { - "fieldname": "column_break_6", - "fieldtype": "Section Break", - "label": "Membership Invoicing" - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "description": "This company will be set for the Memberships created via webhook.", - "fieldname": "company", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Company", - "options": "Company", - "reqd": 1 - }, - { - "default": "0", - "depends_on": "eval:doc.allow_invoicing && doc.send_email", - "fieldname": "send_invoice", - "fieldtype": "Check", - "label": "Send Invoice with Email" - }, - { - "default": "0", - "fieldname": "send_email", - "fieldtype": "Check", - "label": "Send Membership Acknowledgement" - }, - { - "depends_on": "eval: doc.send_invoice", - "fieldname": "inv_print_format", - "fieldtype": "Link", - "label": "Invoice Print Format", - "mandatory_depends_on": "eval: doc.send_invoice", - "options": "Print Format" - }, - { - "depends_on": "eval:doc.send_email", - "fieldname": "membership_print_format", - "fieldtype": "Link", - "label": "Membership Print Format", - "options": "Print Format" - }, - { - "depends_on": "eval:doc.send_email", - "fieldname": "email_template", - "fieldtype": "Link", - "label": "Email Template", - "mandatory_depends_on": "eval:doc.send_email", - "options": "Email Template" - }, - { - "default": "0", - "fieldname": "allow_invoicing", - "fieldtype": "Check", - "label": "Allow Invoicing for Memberships", - "mandatory_depends_on": "eval:doc.send_invoice || doc.make_payment_entry" - }, - { - "default": "0", - "depends_on": "eval:doc.allow_invoicing", - "description": "Automatically create an invoice when payment is authorized from a web form entry", - "fieldname": "automate_membership_invoicing", - "fieldtype": "Check", - "label": "Automate Invoicing for Web Forms" - }, - { - "default": "0", - "depends_on": "eval:doc.allow_invoicing", - "description": "Auto creates Payment Entry for Sales Invoices created for Membership from web forms.", - "fieldname": "automate_membership_payment_entries", - "fieldtype": "Check", - "label": "Automate Payment Entry Creation" - }, - { - "default": "0", - "fieldname": "enable_razorpay_for_memberships", - "fieldtype": "Check", - "label": "Enable RazorPay For Memberships" - }, - { - "depends_on": "eval:doc.automate_membership_payment_entries", - "description": "Account for accepting membership payments", - "fieldname": "membership_payment_account", - "fieldtype": "Link", - "label": "Membership Payment To", - "mandatory_depends_on": "eval:doc.automate_membership_payment_entries", - "options": "Account" - }, - { - "fieldname": "membership_webhook_secret", - "fieldtype": "Password", - "label": "Membership Webhook Secret", - "read_only": 1 - }, - { - "fieldname": "donation_webhook_secret", - "fieldtype": "Password", - "label": "Donation Webhook Secret", - "read_only": 1 - }, - { - "depends_on": "automate_donation_payment_entries", - "description": "Account for accepting donation payments", - "fieldname": "donation_payment_account", - "fieldtype": "Link", - "label": "Donation Payment To", - "mandatory_depends_on": "automate_donation_payment_entries", - "options": "Account" - }, - { - "default": "0", - "description": "Auto creates Payment Entry for Donations created from web forms.", - "fieldname": "automate_donation_payment_entries", - "fieldtype": "Check", - "label": "Automate Donation Payment Entries" - }, - { - "depends_on": "eval:doc.allow_invoicing", - "fieldname": "membership_debit_account", - "fieldtype": "Link", - "label": "Debit Account", - "mandatory_depends_on": "eval:doc.allow_invoicing", - "options": "Account" - }, - { - "depends_on": "automate_donation_payment_entries", - "fieldname": "donation_debit_account", - "fieldtype": "Link", - "label": "Debit Account", - "mandatory_depends_on": "automate_donation_payment_entries", - "options": "Account" - }, - { - "description": "This company will be set for the Donations created via webhook.", - "fieldname": "donation_company", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Company", - "options": "Company", - "reqd": 1 - }, - { - "fieldname": "donation_settings_section", - "fieldtype": "Section Break", - "label": "Donation Settings" - }, - { - "fieldname": "column_break_22", - "fieldtype": "Column Break" - }, - { - "description": "This Donor Type will be set for the Donor created via Donation web form entry.", - "fieldname": "default_donor_type", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Default Donor Type", - "options": "Donor Type", - "reqd": 1 - }, - { - "fieldname": "section_break_27", - "fieldtype": "Section Break" - }, - { - "description": "The user that will be used to create Donations, Memberships, Invoices, and Payment Entries. This user should have the relevant permissions.", - "fieldname": "creation_user", - "fieldtype": "Link", - "label": "Creation User", - "options": "User", - "reqd": 1 - } - ], - "index_web_pages_for_search": 1, - "issingle": 1, - "links": [], - "modified": "2021-03-11 10:43:38.124240", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Non Profit Settings", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "role": "System Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - }, - { - "email": 1, - "print": 1, - "read": 1, - "role": "Non Profit Member", - "share": 1 - } - ], - "quick_entry": 1, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py deleted file mode 100644 index ace6605542..0000000000 --- a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ -from frappe.integrations.utils import get_payment_gateway_controller -from frappe.model.document import Document - - -class NonProfitSettings(Document): - @frappe.whitelist() - def generate_webhook_secret(self, field="membership_webhook_secret"): - key = frappe.generate_hash(length=20) - self.set(field, key) - self.save() - - secret_for = "Membership" if field == "membership_webhook_secret" else "Donation" - - frappe.msgprint( - _("Here is your webhook secret for {0} API, this will be shown to you only once.").format(secret_for) + "

" + key, - _("Webhook Secret") - ) - - @frappe.whitelist() - def revoke_key(self, key): - self.set(key, None) - self.save() - - def get_webhook_secret(self, endpoint="Membership"): - fieldname = "membership_webhook_secret" if endpoint == "Membership" else "donation_webhook_secret" - return self.get_password(fieldname=fieldname, raise_exception=False) - -@frappe.whitelist() -def get_plans_for_membership(*args, **kwargs): - controller = get_payment_gateway_controller("Razorpay") - plans = controller.get_plans() - return [plan.get("item") for plan in plans.get("items")] diff --git a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py deleted file mode 100644 index 51d1ba02eb..0000000000 --- a/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -# import frappe -import unittest - - -class TestNonProfitSettings(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/volunteer/__init__.py b/erpnext/non_profit/doctype/volunteer/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/volunteer/test_volunteer.py b/erpnext/non_profit/doctype/volunteer/test_volunteer.py deleted file mode 100644 index 0a0ab2cf34..0000000000 --- a/erpnext/non_profit/doctype/volunteer/test_volunteer.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestVolunteer(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.js b/erpnext/non_profit/doctype/volunteer/volunteer.js deleted file mode 100644 index ac93d8c801..0000000000 --- a/erpnext/non_profit/doctype/volunteer/volunteer.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Volunteer', { - refresh: function(frm) { - - frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Volunteer'}; - - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); - - if(!frm.doc.__islocal) { - frappe.contacts.render_address_and_contact(frm); - } else { - frappe.contacts.clear_address_and_contact(frm); - } - } -}); diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.json b/erpnext/non_profit/doctype/volunteer/volunteer.json deleted file mode 100644 index 08b7f87b2a..0000000000 --- a/erpnext/non_profit/doctype/volunteer/volunteer.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "actions": [], - "allow_rename": 1, - "autoname": "field:email", - "creation": "2017-09-19 16:16:45.676019", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "volunteer_name", - "column_break_5", - "volunteer_type", - "email", - "image", - "address_contacts", - "address_html", - "column_break_9", - "contact_html", - "volunteer_availability_and_skills_details", - "availability", - "availability_timeslot", - "column_break_12", - "volunteer_skills", - "section_break_15", - "note" - ], - "fields": [ - { - "fieldname": "volunteer_name", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Volunteer Name", - "reqd": 1 - }, - { - "fieldname": "column_break_5", - "fieldtype": "Column Break" - }, - { - "fieldname": "volunteer_type", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Volunteer Type", - "options": "Volunteer Type", - "reqd": 1 - }, - { - "fieldname": "email", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Email", - "reqd": 1, - "unique": 1 - }, - { - "fieldname": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "label": "Image", - "no_copy": 1, - "print_hide": 1 - }, - { - "depends_on": "eval:!doc.__islocal;", - "fieldname": "address_contacts", - "fieldtype": "Section Break", - "label": "Address and Contact", - "options": "fa fa-map-marker" - }, - { - "fieldname": "address_html", - "fieldtype": "HTML", - "label": "Address HTML" - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "fieldname": "contact_html", - "fieldtype": "HTML", - "label": "Contact HTML" - }, - { - "fieldname": "volunteer_availability_and_skills_details", - "fieldtype": "Section Break", - "label": "Availability and Skills" - }, - { - "fieldname": "availability", - "fieldtype": "Select", - "label": "Availability", - "options": "\nWeekly\nWeekdays\nWeekends" - }, - { - "fieldname": "availability_timeslot", - "fieldtype": "Select", - "label": "Availability Timeslot", - "options": "\nMorning\nAfternoon\nEvening\nAnytime" - }, - { - "fieldname": "column_break_12", - "fieldtype": "Column Break" - }, - { - "fieldname": "volunteer_skills", - "fieldtype": "Table", - "label": "Volunteer Skills", - "options": "Volunteer Skill" - }, - { - "fieldname": "section_break_15", - "fieldtype": "Section Break" - }, - { - "fieldname": "note", - "fieldtype": "Long Text", - "label": "Note" - } - ], - "image_field": "image", - "links": [], - "modified": "2020-09-16 23:45:15.595952", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Volunteer", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "share": 1, - "write": 1 - } - ], - "quick_entry": 1, - "restrict_to_domain": "Non Profit", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "volunteer_name", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/volunteer/volunteer.py b/erpnext/non_profit/doctype/volunteer/volunteer.py deleted file mode 100644 index b44d67dae3..0000000000 --- a/erpnext/non_profit/doctype/volunteer/volunteer.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.contacts.address_and_contact import load_address_and_contact -from frappe.model.document import Document - - -class Volunteer(Document): - def onload(self): - """Load address and contacts in `__onload`""" - load_address_and_contact(self) diff --git a/erpnext/non_profit/doctype/volunteer_skill/__init__.py b/erpnext/non_profit/doctype/volunteer_skill/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json deleted file mode 100644 index 7d210aa7bd..0000000000 --- a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2017-09-20 15:26:26.453435", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "volunteer_skill", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Volunteer Skill", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2017-12-06 11:54:14.396354", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Volunteer Skill", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py b/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py deleted file mode 100644 index fe7251876d..0000000000 --- a/erpnext/non_profit/doctype/volunteer_skill/volunteer_skill.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class VolunteerSkill(Document): - pass diff --git a/erpnext/non_profit/doctype/volunteer_type/__init__.py b/erpnext/non_profit/doctype/volunteer_type/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py deleted file mode 100644 index cef27c83a5..0000000000 --- a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestVolunteerType(unittest.TestCase): - pass diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js deleted file mode 100644 index 5c17505be9..0000000000 --- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Volunteer Type', { - refresh: function() { - - } -}); diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json deleted file mode 100644 index 256b25fe91..0000000000 --- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "prompt", - "beta": 0, - "creation": "2017-09-19 16:13:07.763273", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amount", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-12-06 11:52:08.800425", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Volunteer Type", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Non Profit Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Non Profit", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py b/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py deleted file mode 100644 index 3b1ae1a88e..0000000000 --- a/erpnext/non_profit/doctype/volunteer_type/volunteer_type.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class VolunteerType(Document): - pass diff --git a/erpnext/non_profit/report/__init__.py b/erpnext/non_profit/report/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/report/expiring_memberships/__init__.py b/erpnext/non_profit/report/expiring_memberships/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js deleted file mode 100644 index be3a2438fc..0000000000 --- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt -/* eslint-disable */ - -frappe.query_reports["Expiring Memberships"] = { - "filters": [ - { - "fieldname": "fiscal_year", - "label": __("Fiscal Year"), - "fieldtype": "Link", - "options": "Fiscal Year", - "default": frappe.defaults.get_user_default("fiscal_year"), - "reqd": 1 - }, - { - "fieldname":"month", - "label": __("Month"), - "fieldtype": "Select", - "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", - "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", - "Dec"][frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth()], - } - ] -} diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json deleted file mode 100644 index c311057201..0000000000 --- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2018-05-24 11:44:08.942809", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "letter_head": "ERPNext Foundation", - "modified": "2018-05-24 11:44:08.942809", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Expiring Memberships", - "owner": "Administrator", - "ref_doctype": "Membership", - "report_name": "Expiring Memberships", - "report_type": "Script Report", - "roles": [ - { - "role": "Non Profit Manager" - }, - { - "role": "Non Profit Member" - } - ] -} \ No newline at end of file diff --git a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py b/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py deleted file mode 100644 index 3ddbfdc3b0..0000000000 --- a/erpnext/non_profit/report/expiring_memberships/expiring_memberships.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ - - -def execute(filters=None): - columns = get_columns(filters) - data = get_data(filters) - return columns, data - -def get_columns(filters): - return [ - _("Membership Type") + ":Link/Membership Type:100", _("Membership ID") + ":Link/Membership:140", - _("Member ID") + ":Link/Member:140", _("Member Name") + ":Data:140", _("Email") + ":Data:140", - _("Expiring On") + ":Date:120" - ] - -def get_data(filters): - - filters["month"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].index(filters.month) + 1 - - return frappe.db.sql(""" - select ms.membership_type,ms.name,m.name,m.member_name,m.email,ms.max_membership_date - from `tabMember` m - inner join (select name,membership_type,max(to_date) as max_membership_date,member - from `tabMembership` - where paid = 1 - group by member - order by max_membership_date asc) ms - on m.name = ms.member - where month(max_membership_date) = %(month)s and year(max_membership_date) = %(year)s """,{'month': filters.get('month'),'year':filters.get('fiscal_year')}) diff --git a/erpnext/non_profit/utils.py b/erpnext/non_profit/utils.py deleted file mode 100644 index 47ea5f5783..0000000000 --- a/erpnext/non_profit/utils.py +++ /dev/null @@ -1,12 +0,0 @@ -import frappe - - -def get_company(): - company = frappe.defaults.get_defaults().company - if company: - return company - else: - company = frappe.get_list("Company", limit=1) - if company: - return company[0].name - return None diff --git a/erpnext/non_profit/web_form/__init__.py b/erpnext/non_profit/web_form/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/web_form/certification_application/__init__.py b/erpnext/non_profit/web_form/certification_application/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.js b/erpnext/non_profit/web_form/certification_application/certification_application.js deleted file mode 100644 index 8b455edafa..0000000000 --- a/erpnext/non_profit/web_form/certification_application/certification_application.js +++ /dev/null @@ -1,16 +0,0 @@ -frappe.ready(function() { - // bind events here - $(".page-header-actions-block .btn-primary, .page-header-actions-block .btn-default").addClass('hidden'); - $(".text-right .btn-primary").addClass('hidden'); - - if (frappe.utils.get_url_arg('name')) { - $('.page-content .btn-form-submit').addClass('hidden'); - } else { - user_name = frappe.full_name - user_email_id = frappe.session.user - $('[data-fieldname="currency"]').val("INR"); - $('[data-fieldname="name_of_applicant"]').val(user_name); - $('[data-fieldname="email"]').val(user_email_id); - $('[data-fieldname="amount"]').val(20000); - } -}) diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.json b/erpnext/non_profit/web_form/certification_application/certification_application.json deleted file mode 100644 index 5fda978fba..0000000000 --- a/erpnext/non_profit/web_form/certification_application/certification_application.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "accept_payment": 1, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 0, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 1, - "amount_field": "amount", - "creation": "2018-06-08 16:24:05.805225", - "doc_type": "Certification Application", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "introduction_text": "", - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2018-06-11 16:11:14.544987", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "certification-application", - "owner": "Administrator", - "payment_button_help": "Pay for your certification using RazorPay", - "payment_button_label": "Pay Now", - "payment_gateway": "Razorpay", - "published": 1, - "route": "certification-application", - "show_sidebar": 1, - "sidebar_items": [], - "success_url": "/certification-application", - "title": "Certification Application", - "web_form_fields": [ - { - "fieldname": "name_of_applicant", - "fieldtype": "Data", - "hidden": 0, - "label": "Name of Applicant", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - }, - { - "fieldname": "email", - "fieldtype": "Link", - "hidden": 0, - "label": "Email", - "max_length": 0, - "max_value": 0, - "options": "User", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "currency", - "fieldtype": "Select", - "hidden": 0, - "label": "Currency", - "max_length": 0, - "max_value": 0, - "options": "USD\nINR", - "read_only": 1, - "reqd": 0 - }, - { - "fieldname": "amount", - "fieldtype": "Float", - "hidden": 0, - "label": "Amount", - "max_length": 0, - "max_value": 0, - "read_only": 1, - "reqd": 0 - } - ] -} \ No newline at end of file diff --git a/erpnext/non_profit/web_form/certification_application/certification_application.py b/erpnext/non_profit/web_form/certification_application/certification_application.py deleted file mode 100644 index 02e3e93333..0000000000 --- a/erpnext/non_profit/web_form/certification_application/certification_application.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_context(context): - # do your magic here - pass diff --git a/erpnext/non_profit/web_form/certification_application_usd/__init__.py b/erpnext/non_profit/web_form/certification_application_usd/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js deleted file mode 100644 index 005d1dd6c1..0000000000 --- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.js +++ /dev/null @@ -1,16 +0,0 @@ -frappe.ready(function() { - // bind events here - $(".page-header-actions-block .btn-primary, .page-header-actions-block .btn-default").addClass('hidden'); - $(".text-right .btn-primary").addClass('hidden'); - - if (frappe.utils.get_url_arg('name')) { - $('.page-content .btn-form-submit').addClass('hidden'); - } else { - user_name = frappe.full_name - user_email_id = frappe.session.user - $('[data-fieldname="currency"]').val("USD"); - $('[data-fieldname="name_of_applicant"]').val(user_name); - $('[data-fieldname="email"]').val(user_email_id); - $('[data-fieldname="amount"]').val(300); - } -}) diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json deleted file mode 100644 index 266109f580..0000000000 --- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "accept_payment": 1, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 0, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 1, - "amount_field": "amount", - "creation": "2018-06-13 09:22:48.262441", - "currency": "USD", - "doc_type": "Certification Application", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "introduction_text": "", - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2018-06-13 09:26:35.502064", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "certification-application-usd", - "owner": "Administrator", - "payment_button_help": "Pay for your certification using PayPal", - "payment_button_label": "Pay Now", - "payment_gateway": "PayPal", - "published": 1, - "route": "certification-application-usd", - "show_sidebar": 1, - "sidebar_items": [], - "success_url": "/certification-application-usd", - "title": "Certification Application USD", - "web_form_fields": [ - { - "fieldname": "name_of_applicant", - "fieldtype": "Data", - "hidden": 0, - "label": "Name of Applicant", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - }, - { - "fieldname": "email", - "fieldtype": "Link", - "hidden": 0, - "label": "Email", - "max_length": 0, - "max_value": 0, - "options": "User", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "currency", - "fieldtype": "Select", - "hidden": 0, - "label": "Currency", - "max_length": 0, - "max_value": 0, - "options": "USD\nINR", - "read_only": 1, - "reqd": 0 - }, - { - "fieldname": "amount", - "fieldtype": "Float", - "hidden": 0, - "label": "Amount", - "max_length": 0, - "max_value": 0, - "read_only": 1, - "reqd": 0 - } - ] -} \ No newline at end of file diff --git a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py b/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py deleted file mode 100644 index 02e3e93333..0000000000 --- a/erpnext/non_profit/web_form/certification_application_usd/certification_application_usd.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_context(context): - # do your magic here - pass diff --git a/erpnext/non_profit/web_form/grant_application/__init__.py b/erpnext/non_profit/web_form/grant_application/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.js b/erpnext/non_profit/web_form/grant_application/grant_application.js deleted file mode 100644 index f09e540919..0000000000 --- a/erpnext/non_profit/web_form/grant_application/grant_application.js +++ /dev/null @@ -1,3 +0,0 @@ -frappe.ready(function() { - // bind events here -}); diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.json b/erpnext/non_profit/web_form/grant_application/grant_application.json deleted file mode 100644 index 73c9445500..0000000000 --- a/erpnext/non_profit/web_form/grant_application/grant_application.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 1, - "allow_edit": 1, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "creation": "2017-10-30 15:57:10.825188", - "currency": "INR", - "doc_type": "Grant Application", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "introduction_text": "Share as many details as you can to get quick response from organization", - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2017-12-06 12:32:16.893289", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "grant-application", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 1, - "route": "my-grant", - "show_sidebar": 1, - "sidebar_items": [], - "success_url": "/grant-application", - "title": "Grant Application", - "web_form_fields": [ - { - "fieldname": "applicant_type", - "fieldtype": "Select", - "hidden": 0, - "label": "Applicant Type", - "max_length": 0, - "max_value": 0, - "options": "Individual\nOrganization", - "read_only": 0, - "reqd": 1 - }, - { - "fieldname": "applicant_name", - "fieldtype": "Data", - "hidden": 0, - "label": "Name", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1 - }, - { - "fieldname": "email", - "fieldtype": "Data", - "hidden": 0, - "label": "Email Address", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1 - }, - { - "description": "", - "fieldname": "grant_description", - "fieldtype": "Text", - "hidden": 0, - "label": "Please outline your current situation and why you are applying for a grant?", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1 - }, - { - "fieldname": "amount", - "fieldtype": "Float", - "hidden": 0, - "label": "Requested Amount", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - }, - { - "fieldname": "has_any_past_grant_record", - "fieldtype": "Check", - "hidden": 0, - "label": "Have you received any grant from us before?", - "max_length": 0, - "max_value": 0, - "options": "", - "read_only": 0, - "reqd": 0 - }, - { - "fieldname": "published", - "fieldtype": "Check", - "hidden": 0, - "label": "Show on Website", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - } - ] -} \ No newline at end of file diff --git a/erpnext/non_profit/web_form/grant_application/grant_application.py b/erpnext/non_profit/web_form/grant_application/grant_application.py deleted file mode 100644 index 3dfb381f65..0000000000 --- a/erpnext/non_profit/web_form/grant_application/grant_application.py +++ /dev/null @@ -1,4 +0,0 @@ -def get_context(context): - context.no_cache = True - context.parents = [dict(label='View All ', - route='grant-application', title='View All')] diff --git a/erpnext/non_profit/workspace/non_profit/non_profit.json b/erpnext/non_profit/workspace/non_profit/non_profit.json deleted file mode 100644 index fc90475fb3..0000000000 --- a/erpnext/non_profit/workspace/non_profit/non_profit.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "charts": [], - "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Member\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Non Profit Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Membership\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter Member\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Grant Application\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Membership\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Volunteer\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Chapter\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Donation\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tax Exemption Certification (India)\",\"col\":4}}]", - "creation": "2020-03-02 17:23:47.811421", - "docstatus": 0, - "doctype": "Workspace", - "for_user": "", - "hide_custom": 0, - "icon": "non-profit", - "idx": 0, - "label": "Non Profit", - "links": [ - { - "hidden": 0, - "is_query_report": 0, - "label": "Loan Management", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Loan Type", - "link_count": 0, - "link_to": "Loan Type", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Loan Application", - "link_count": 0, - "link_to": "Loan Application", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Loan", - "link_count": 0, - "link_to": "Loan", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Grant Application", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Grant Application", - "link_count": 0, - "link_to": "Grant Application", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Membership", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Member", - "link_count": 0, - "link_to": "Member", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Membership", - "link_count": 0, - "link_to": "Membership", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Membership Type", - "link_count": 0, - "link_to": "Membership Type", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Membership Settings", - "link_count": 0, - "link_to": "Non Profit Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Volunteer", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Volunteer", - "link_count": 0, - "link_to": "Volunteer", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Volunteer Type", - "link_count": 0, - "link_to": "Volunteer Type", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Chapter", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Chapter", - "link_count": 0, - "link_to": "Chapter", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Donation", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Donor", - "link_count": 0, - "link_to": "Donor", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Donor Type", - "link_count": 0, - "link_to": "Donor Type", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Donation", - "link_count": 0, - "link_to": "Donation", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Tax Exemption Certification (India)", - "link_count": 0, - "link_type": "DocType", - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Tax Exemption 80G Certificate", - "link_count": 0, - "link_to": "Tax Exemption 80G Certificate", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - } - ], - "modified": "2022-01-13 17:40:50.220877", - "modified_by": "Administrator", - "module": "Non Profit", - "name": "Non Profit", - "owner": "Administrator", - "parent_page": "", - "public": 1, - "restrict_to_domain": "Non Profit", - "roles": [], - "sequence_id": 18.0, - "shortcuts": [ - { - "label": "Member", - "link_to": "Member", - "type": "DocType" - }, - { - "label": "Non Profit Settings", - "link_to": "Non Profit Settings", - "type": "DocType" - }, - { - "label": "Membership", - "link_to": "Membership", - "type": "DocType" - }, - { - "label": "Chapter", - "link_to": "Chapter", - "type": "DocType" - }, - { - "label": "Chapter Member", - "link_to": "Chapter Member", - "type": "DocType" - } - ], - "title": "Non Profit" -} \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 52c29b22b9..12af8f800a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -332,6 +332,7 @@ erpnext.patches.v13_0.hospitality_deprecation_warning erpnext.patches.v13_0.update_asset_quantity_field erpnext.patches.v13_0.delete_bank_reconciliation_detail erpnext.patches.v13_0.enable_provisional_accounting +erpnext.patches.v13_0.non_profit_deprecation_warning [post_model_sync] erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents @@ -353,4 +354,6 @@ erpnext.patches.v13_0.update_reserved_qty_closed_wo erpnext.patches.v13_0.update_exchange_rate_settings erpnext.patches.v14_0.delete_amazon_mws_doctype erpnext.patches.v13_0.set_work_order_qty_in_so_from_mr +erpnext.patches.v13_0.update_accounts_in_loan_docs erpnext.patches.v14_0.update_batch_valuation_flag +erpnext.patches.v14_0.delete_non_profit_doctypes \ No newline at end of file diff --git a/erpnext/patches/v13_0/non_profit_deprecation_warning.py b/erpnext/patches/v13_0/non_profit_deprecation_warning.py new file mode 100644 index 0000000000..5b54b25a5b --- /dev/null +++ b/erpnext/patches/v13_0/non_profit_deprecation_warning.py @@ -0,0 +1,10 @@ +import click + + +def execute(): + + click.secho( + "Non Profit Domain is moved to a separate app and will be removed from ERPNext in version-14.\n" + "When upgrading to ERPNext version-14, please install the app to continue using the Non Profit domain: https://github.com/frappe/non_profit", + fg="yellow", + ) diff --git a/erpnext/patches/v13_0/update_accounts_in_loan_docs.py b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py new file mode 100644 index 0000000000..440f912be2 --- /dev/null +++ b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py @@ -0,0 +1,37 @@ +import frappe + + +def execute(): + ld = frappe.qb.DocType("Loan Disbursement").as_("ld") + lr = frappe.qb.DocType("Loan Repayment").as_("lr") + loan = frappe.qb.DocType("Loan") + + frappe.qb.update( + ld + ).inner_join( + loan + ).on( + loan.name == ld.against_loan + ).set( + ld.disbursement_account, loan.disbursement_account + ).set( + ld.loan_account, loan.loan_account + ).where( + ld.docstatus < 2 + ).run() + + frappe.qb.update( + lr + ).inner_join( + loan + ).on( + loan.name == lr.against_loan + ).set( + lr.payment_account, loan.payment_account + ).set( + lr.loan_account, loan.loan_account + ).set( + lr.penalty_income_account, loan.penalty_income_account + ).where( + lr.docstatus < 2 + ).run() diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py new file mode 100644 index 0000000000..565b10cbb8 --- /dev/null +++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py @@ -0,0 +1,63 @@ +import frappe + + +def execute(): + frappe.delete_doc("Module Def", "Non Profit", ignore_missing=True, force=True) + + frappe.delete_doc("Workspace", "Non Profit", ignore_missing=True, force=True) + + print_formats = frappe.get_all("Print Format", {"module": "Non Profit", "standard": "Yes"}, pluck='name') + for print_format in print_formats: + frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True) + + print_formats = ['80G Certificate for Membership', '80G Certificate for Donation'] + for print_format in print_formats: + frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True) + + reports = frappe.get_all("Report", {"module": "Non Profit", "is_standard": "Yes"}, pluck='name') + for report in reports: + frappe.delete_doc("Report", report, ignore_missing=True, force=True) + + dashboards = frappe.get_all("Dashboard", {"module": "Non Profit", "is_standard": 1}, pluck='name') + for dashboard in dashboards: + frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True) + + doctypes = frappe.get_all("DocType", {"module": "Non Profit", "custom": 0}, pluck='name') + for doctype in doctypes: + frappe.delete_doc("DocType", doctype, ignore_missing=True) + + doctypes = ['Tax Exemption 80G Certificate', 'Tax Exemption 80G Certificate Detail'] + for doctype in doctypes: + frappe.delete_doc("DocType", doctype, ignore_missing=True) + + forms = ['grant-application', 'certification-application', 'certification-application-usd'] + for form in forms: + frappe.delete_doc("Web Form", form, ignore_missing=True, force=True) + + custom_records = [ + {"doctype": "Party Type", "name": "Member"}, + {"doctype": "Party Type", "name": "Donor"}, + ] + for record in custom_records: + try: + frappe.delete_doc(record['doctype'], record['name'], ignore_missing=True) + except frappe.LinkExistsError: + pass + + custom_fields = { + 'Member': ['pan_number'], + 'Donor': ['pan_number'], + 'Company': [ + 'non_profit_section', 'company_80g_number', 'with_effect_from', + 'non_profit_column_break', 'pan_details' + ], + } + + for doc, fields in custom_fields.items(): + filters = { + 'dt': doc, + 'fieldname': ['in', fields] + } + records = frappe.get_all('Custom Field', filters=filters, pluck='name') + for record in records: + frappe.delete_doc('Custom Field', record, ignore_missing=True, force=True) diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py index b30d983adc..c3be146bec 100644 --- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py +++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py @@ -21,7 +21,7 @@ class TestHomepageSection(unittest.TestCase): {'title': 'Card 2', 'subtitle': 'Subtitle 2', 'content': 'This is test card 2', 'image': 'test.jpg'}, ], 'no_of_columns': 3 - }).insert() + }).insert(ignore_if_duplicate=True) except frappe.DuplicateEntryError: pass diff --git a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js index ca73393c54..214a1be134 100644 --- a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js +++ b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js @@ -181,6 +181,12 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager { fieldname: "journal_entry", onchange: () => this.update_options(), }, + { + fieldtype: "Check", + label: "Loan Repayment", + fieldname: "loan_repayment", + onchange: () => this.update_options(), + }, { fieldname: "column_break_5", fieldtype: "Column Break", @@ -191,13 +197,18 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager { fieldname: "sales_invoice", onchange: () => this.update_options(), }, - { fieldtype: "Check", label: "Purchase Invoice", fieldname: "purchase_invoice", onchange: () => this.update_options(), }, + { + fieldtype: "Check", + label: "Show Only Exact Amount", + fieldname: "exact_match", + onchange: () => this.update_options(), + }, { fieldname: "column_break_5", fieldtype: "Column Break", @@ -210,8 +221,8 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager { }, { fieldtype: "Check", - label: "Show Only Exact Amount", - fieldname: "exact_match", + label: "Loan Disbursement", + fieldname: "loan_disbursement", onchange: () => this.update_options(), }, { diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index ae8c0c8c6d..00373a6513 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -2285,13 +2285,17 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } coupon_code() { - var me = this; - frappe.run_serially([ - () => this.frm.doc.ignore_pricing_rule=1, - () => me.ignore_pricing_rule(), - () => this.frm.doc.ignore_pricing_rule=0, - () => me.apply_pricing_rule() - ]); + if (this.frm.doc.coupon_code || this.frm._last_coupon_code) { + // reset pricing rules if coupon code is set or is unset + const _ignore_pricing_rule = this.frm.doc.ignore_pricing_rule; + return frappe.run_serially([ + () => this.frm.doc.ignore_pricing_rule=1, + () => this.frm.trigger('ignore_pricing_rule'), + () => this.frm.doc.ignore_pricing_rule=_ignore_pricing_rule, + () => this.frm.trigger('apply_pricing_rule'), + () => this.frm._last_coupon_code = this.frm.doc.coupon_code + ]); + } } }; diff --git a/erpnext/public/js/education/student_button.html b/erpnext/public/js/education/student_button.html deleted file mode 100644 index b64c73a43c..0000000000 --- a/erpnext/public/js/education/student_button.html +++ /dev/null @@ -1,17 +0,0 @@ -
-
- -
-
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js index b3a68b3862..8409e78860 100644 --- a/erpnext/public/js/erpnext.bundle.js +++ b/erpnext/public/js/erpnext.bundle.js @@ -16,7 +16,6 @@ import "./templates/item_quick_entry.html"; import "./utils/item_quick_entry"; import "./utils/customer_quick_entry"; import "./utils/supplier_quick_entry"; -import "./education/student_button.html"; import "./education/assessment_result_tool.html"; import "./call_popup/call_popup"; import "./utils/dimension_tree_filter"; diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js index 831626aa91..a585aa614f 100644 --- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js +++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js @@ -304,12 +304,13 @@ erpnext.HierarchyChart = class { } get_child_nodes(node_id) { + let me = this; return new Promise(resolve => { frappe.call({ - method: this.method, + method: me.method, args: { parent: node_id, - company: this.company + company: me.company } }).then(r => resolve(r.message)); }); @@ -350,12 +351,13 @@ erpnext.HierarchyChart = class { } get_all_nodes() { + let me = this; return new Promise(resolve => { frappe.call({ method: 'erpnext.utilities.hierarchy_chart.get_all_nodes', args: { - method: this.method, - company: this.company + method: me.method, + company: me.company }, callback: (r) => { resolve(r.message); @@ -427,8 +429,8 @@ erpnext.HierarchyChart = class { add_connector(parent_id, child_id) { // using pure javascript for better performance - const parent_node = document.querySelector(`#${parent_id}`); - const child_node = document.querySelector(`#${child_id}`); + const parent_node = document.getElementById(`${parent_id}`); + const child_node = document.getElementById(`${child_id}`); let path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js index 0a8ba78f64..52236e7df9 100644 --- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js +++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_mobile.js @@ -235,7 +235,7 @@ erpnext.HierarchyChartMobile = class { let me = this; return new Promise(resolve => { frappe.call({ - method: this.method, + method: me.method, args: { parent: node_id, company: me.company, @@ -286,8 +286,8 @@ erpnext.HierarchyChartMobile = class { } add_connector(parent_id, child_id) { - const parent_node = document.querySelector(`#${parent_id}`); - const child_node = document.querySelector(`#${child_id}`); + const parent_node = document.getElementById(`${parent_id}`); + const child_node = document.getElementById(`${child_id}`); const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); @@ -518,7 +518,8 @@ erpnext.HierarchyChartMobile = class { level.nextAll('li').remove(); let node_object = this.nodes[node.id]; - let current_node = level.find(`#${node.id}`).detach(); + let current_node = level.find(`[id="${node.id}"]`).detach(); + current_node.removeClass('active-child active-path'); node_object.expanded = 0; diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js index e746ce9ae0..83b69aebc5 100644 --- a/erpnext/public/js/setup_wizard.js +++ b/erpnext/public/js/setup_wizard.js @@ -78,11 +78,11 @@ erpnext.setup.slides_settings = [ slide.get_input("company_name").on("change", function () { var parts = slide.get_input("company_name").val().split(" "); var abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join(""); - slide.get_field("company_abbr").set_value(abbr.slice(0, 5).toUpperCase()); + slide.get_field("company_abbr").set_value(abbr.slice(0, 10).toUpperCase()); }).val(frappe.boot.sysdefaults.company_name || "").trigger("change"); slide.get_input("company_abbr").on("change", function () { - if (slide.get_input("company_abbr").val().length > 5) { + if (slide.get_input("company_abbr").val().length > 10) { frappe.msgprint(__("Company Abbreviation cannot have more than 5 characters")); slide.get_field("company_abbr").set_value(""); } @@ -96,7 +96,7 @@ erpnext.setup.slides_settings = [ if (!this.values.company_abbr) { return false; } - if (this.values.company_abbr.length > 5) { + if (this.values.company_abbr.length > 10) { return false; } return true; diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 4b645b9dde..666043b219 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -338,14 +338,14 @@ body.product-page { .btn-add-to-wishlist { svg use { - stroke: #F47A7A; + --icon-stroke: #F47A7A; } } .btn-view-in-wishlist { svg use { fill: #F47A7A; - stroke: none; + --icon-stroke: none; } } @@ -1022,7 +1022,7 @@ body.product-page { .not-wished { cursor: pointer; - stroke: #F47A7A !important; + --icon-stroke: #F47A7A !important; &:hover { fill: #F47A7A; @@ -1030,7 +1030,7 @@ body.product-page { } .wished { - stroke: none; + --icon-stroke: none; fill: #F47A7A !important; } diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js deleted file mode 100644 index 54cde9c0cf..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Tax Exemption 80G Certificate', { - refresh: function(frm) { - if (frm.doc.donor) { - frm.set_query('donation', function() { - return { - filters: { - docstatus: 1, - donor: frm.doc.donor - } - }; - }); - } - }, - - recipient: function(frm) { - if (frm.doc.recipient === 'Donor') { - frm.set_value({ - 'member': '', - 'member_name': '', - 'member_email': '', - 'member_pan_number': '', - 'fiscal_year': '', - 'total': 0, - 'payments': [] - }); - } else { - frm.set_value({ - 'donor': '', - 'donor_name': '', - 'donor_email': '', - 'donor_pan_number': '', - 'donation': '', - 'date_of_donation': '', - 'amount': 0, - 'mode_of_payment': '', - 'razorpay_payment_id': '' - }); - } - }, - - get_payments: function(frm) { - frm.call({ - doc: frm.doc, - method: 'get_payments', - freeze: true - }); - }, - - company: function(frm) { - if ((frm.doc.member || frm.doc.donor) && frm.doc.company) { - frm.call({ - doc: frm.doc, - method: 'set_company_address', - freeze: true - }); - } - }, - - donation: function(frm) { - if (frm.doc.recipient === 'Donor' && !frm.doc.donor) { - frappe.msgprint(__('Please select donor first')); - } - } -}); diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json deleted file mode 100644 index 9eee722f42..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json +++ /dev/null @@ -1,297 +0,0 @@ -{ - "actions": [], - "autoname": "naming_series:", - "creation": "2021-02-15 12:37:21.577042", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "naming_series", - "recipient", - "member", - "member_name", - "member_email", - "member_pan_number", - "donor", - "donor_name", - "donor_email", - "donor_pan_number", - "column_break_4", - "date", - "fiscal_year", - "section_break_11", - "company", - "company_address", - "company_address_display", - "column_break_14", - "company_pan_number", - "company_80g_number", - "company_80g_wef", - "title", - "section_break_6", - "get_payments", - "payments", - "total", - "donation_details_section", - "donation", - "date_of_donation", - "amount", - "column_break_27", - "mode_of_payment", - "razorpay_payment_id" - ], - "fields": [ - { - "fieldname": "recipient", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Certificate Recipient", - "options": "Member\nDonor", - "reqd": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fieldname": "member", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Member", - "mandatory_depends_on": "eval:doc.recipient === \"Member\";", - "options": "Member" - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fetch_from": "member.member_name", - "fieldname": "member_name", - "fieldtype": "Data", - "label": "Member Name", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Donor\";", - "fieldname": "donor", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Donor", - "mandatory_depends_on": "eval:doc.recipient === \"Donor\";", - "options": "Donor" - }, - { - "fieldname": "column_break_4", - "fieldtype": "Column Break" - }, - { - "fieldname": "date", - "fieldtype": "Date", - "label": "Date", - "reqd": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fieldname": "section_break_6", - "fieldtype": "Section Break" - }, - { - "fieldname": "payments", - "fieldtype": "Table", - "label": "Payments", - "options": "Tax Exemption 80G Certificate Detail" - }, - { - "fieldname": "total", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Total", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fieldname": "fiscal_year", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Fiscal Year", - "options": "Fiscal Year" - }, - { - "fieldname": "company", - "fieldtype": "Link", - "label": "Company", - "options": "Company", - "reqd": 1 - }, - { - "fieldname": "get_payments", - "fieldtype": "Button", - "label": "Get Memberships" - }, - { - "fieldname": "naming_series", - "fieldtype": "Select", - "label": "Naming Series", - "options": "NPO-80G-.YYYY.-" - }, - { - "fieldname": "section_break_11", - "fieldtype": "Section Break", - "label": "Company Details" - }, - { - "fieldname": "company_address", - "fieldtype": "Link", - "label": "Company Address", - "options": "Address" - }, - { - "fieldname": "column_break_14", - "fieldtype": "Column Break" - }, - { - "fetch_from": "company.pan_details", - "fieldname": "company_pan_number", - "fieldtype": "Data", - "label": "PAN Number", - "read_only": 1 - }, - { - "fieldname": "company_address_display", - "fieldtype": "Small Text", - "hidden": 1, - "label": "Company Address Display", - "print_hide": 1, - "read_only": 1 - }, - { - "fetch_from": "company.company_80g_number", - "fieldname": "company_80g_number", - "fieldtype": "Data", - "label": "80G Number", - "read_only": 1 - }, - { - "fetch_from": "company.with_effect_from", - "fieldname": "company_80g_wef", - "fieldtype": "Date", - "label": "80G With Effect From", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Donor\";", - "fieldname": "donation_details_section", - "fieldtype": "Section Break", - "label": "Donation Details" - }, - { - "fieldname": "donation", - "fieldtype": "Link", - "label": "Donation", - "mandatory_depends_on": "eval:doc.recipient === \"Donor\";", - "options": "Donation" - }, - { - "fetch_from": "donation.amount", - "fieldname": "amount", - "fieldtype": "Currency", - "label": "Amount", - "read_only": 1 - }, - { - "fetch_from": "donation.mode_of_payment", - "fieldname": "mode_of_payment", - "fieldtype": "Link", - "label": "Mode of Payment", - "options": "Mode of Payment", - "read_only": 1 - }, - { - "fetch_from": "donation.razorpay_payment_id", - "fieldname": "razorpay_payment_id", - "fieldtype": "Data", - "label": "RazorPay Payment ID", - "read_only": 1 - }, - { - "fetch_from": "donation.date", - "fieldname": "date_of_donation", - "fieldtype": "Date", - "label": "Date of Donation", - "read_only": 1 - }, - { - "fieldname": "column_break_27", - "fieldtype": "Column Break" - }, - { - "depends_on": "eval:doc.recipient === \"Donor\";", - "fetch_from": "donor.donor_name", - "fieldname": "donor_name", - "fieldtype": "Data", - "label": "Donor Name", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Donor\";", - "fetch_from": "donor.email", - "fieldname": "donor_email", - "fieldtype": "Data", - "label": "Email", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fetch_from": "member.email_id", - "fieldname": "member_email", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Email", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Member\";", - "fetch_from": "member.pan_number", - "fieldname": "member_pan_number", - "fieldtype": "Data", - "label": "PAN Details", - "read_only": 1 - }, - { - "depends_on": "eval:doc.recipient === \"Donor\";", - "fetch_from": "donor.pan_number", - "fieldname": "donor_pan_number", - "fieldtype": "Data", - "label": "PAN Details", - "read_only": 1 - }, - { - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "label": "Title", - "print_hide": 1 - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-02-22 00:03:34.215633", - "modified_by": "Administrator", - "module": "Regional", - "name": "Tax Exemption 80G Certificate", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "search_fields": "member, member_name", - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "title", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py deleted file mode 100644 index 0f0897841b..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -import frappe -from frappe import _ -from frappe.contacts.doctype.address.address import get_company_address -from frappe.model.document import Document -from frappe.utils import flt, get_link_to_form, getdate - -from erpnext.accounts.utils import get_fiscal_year - - -class TaxExemption80GCertificate(Document): - def validate(self): - self.validate_date() - self.validate_duplicates() - self.validate_company_details() - self.set_company_address() - self.calculate_total() - self.set_title() - - def validate_date(self): - if self.recipient == 'Member': - if getdate(self.date): - fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True) - - if not (fiscal_year.year_start_date <= getdate(self.date) \ - <= fiscal_year.year_end_date): - frappe.throw(_('The Certificate Date is not in the Fiscal Year {0}').format(frappe.bold(self.fiscal_year))) - - def validate_duplicates(self): - if self.recipient == 'Donor': - certificate = frappe.db.exists(self.doctype, { - 'donation': self.donation, - 'name': ('!=', self.name) - }) - if certificate: - frappe.throw(_('An 80G Certificate {0} already exists for the donation {1}').format( - get_link_to_form(self.doctype, certificate), frappe.bold(self.donation) - ), title=_('Duplicate Certificate')) - - def validate_company_details(self): - fields = ['company_80g_number', 'with_effect_from', 'pan_details'] - company_details = frappe.db.get_value('Company', self.company, fields, as_dict=True) - if not company_details.company_80g_number: - frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('80G Number'), - get_link_to_form('Company', self.company))) - - if not company_details.pan_details: - frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('PAN Number'), - get_link_to_form('Company', self.company))) - - @frappe.whitelist() - def set_company_address(self): - address = get_company_address(self.company) - self.company_address = address.company_address - self.company_address_display = address.company_address_display - - def calculate_total(self): - if self.recipient == 'Donor': - return - - total = 0 - for entry in self.payments: - total += flt(entry.amount) - self.total = total - - def set_title(self): - if self.recipient == 'Member': - self.title = self.member_name - else: - self.title = self.donor_name - - @frappe.whitelist() - def get_payments(self): - if not self.member: - frappe.throw(_('Please select a Member first.')) - - fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True) - - memberships = frappe.db.get_all('Membership', { - 'member': self.member, - 'from_date': ['between', (fiscal_year.year_start_date, fiscal_year.year_end_date)], - 'membership_status': ('!=', 'Cancelled') - }, ['from_date', 'amount', 'name', 'invoice', 'payment_id'], order_by='from_date') - - if not memberships: - frappe.msgprint(_('No Membership Payments found against the Member {0}').format(self.member)) - - total = 0 - self.payments = [] - - for doc in memberships: - self.append('payments', { - 'date': doc.from_date, - 'amount': doc.amount, - 'invoice_id': doc.invoice, - 'razorpay_payment_id': doc.payment_id, - 'membership': doc.name - }) - total += flt(doc.amount) - - self.total = total diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py deleted file mode 100644 index 6fa3b85d06..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - -import frappe -from frappe.utils import getdate - -from erpnext.accounts.utils import get_fiscal_year -from erpnext.non_profit.doctype.donation.donation import create_donation -from erpnext.non_profit.doctype.donation.test_donation import ( - create_donor, - create_donor_type, - create_mode_of_payment, -) -from erpnext.non_profit.doctype.member.member import create_member -from erpnext.non_profit.doctype.membership.test_membership import make_membership, setup_membership - - -class TestTaxExemption80GCertificate(unittest.TestCase): - def setUp(self): - frappe.db.sql('delete from `tabTax Exemption 80G Certificate`') - frappe.db.sql('delete from `tabMembership`') - create_donor_type() - settings = frappe.get_doc('Non Profit Settings') - settings.company = '_Test Company' - settings.donation_company = '_Test Company' - settings.default_donor_type = '_Test Donor' - settings.creation_user = 'Administrator' - settings.save() - - company = frappe.get_doc('Company', '_Test Company') - company.pan_details = 'BBBTI3374C' - company.company_80g_number = 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087' - company.with_effect_from = getdate() - company.save() - - def test_duplicate_donation_certificate(self): - donor = create_donor() - create_mode_of_payment() - payment = frappe._dict({ - 'amount': 100, - 'method': 'Debit Card', - 'id': 'pay_MeXAmsgeKOhq7O' - }) - donation = create_donation(donor, payment) - - args = frappe._dict({ - 'recipient': 'Donor', - 'donor': donor.name, - 'donation': donation.name - }) - certificate = create_80g_certificate(args) - certificate.insert() - - # check company details - self.assertEqual(certificate.company_pan_number, 'BBBTI3374C') - self.assertEqual(certificate.company_80g_number, 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087') - - # check donation details - self.assertEqual(certificate.amount, donation.amount) - - duplicate_certificate = create_80g_certificate(args) - # duplicate validation - self.assertRaises(frappe.ValidationError, duplicate_certificate.insert) - - def test_membership_80g_certificate(self): - plan = setup_membership() - - # make test member - member_doc = create_member(frappe._dict({ - 'fullname': "_Test_Member", - 'email': "_test_member_erpnext@example.com", - 'plan_id': plan.name - })) - member_doc.make_customer_and_link() - member = member_doc.name - - membership = make_membership(member, { "from_date": getdate() }) - invoice = membership.generate_invoice(save=True) - - args = frappe._dict({ - 'recipient': 'Member', - 'member': member, - 'fiscal_year': get_fiscal_year(getdate(), as_dict=True).get('name') - }) - certificate = create_80g_certificate(args) - certificate.get_payments() - certificate.insert() - - self.assertEqual(len(certificate.payments), 1) - self.assertEqual(certificate.payments[0].amount, membership.amount) - self.assertEqual(certificate.payments[0].invoice_id, invoice.name) - - -def create_80g_certificate(args): - certificate = frappe.get_doc({ - 'doctype': 'Tax Exemption 80G Certificate', - 'recipient': args.recipient, - 'date': getdate(), - 'company': '_Test Company' - }) - - certificate.update(args) - - return certificate diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json deleted file mode 100644 index dfa817dd27..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "actions": [], - "creation": "2021-02-15 12:43:52.754124", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "date", - "amount", - "invoice_id", - "column_break_4", - "razorpay_payment_id", - "membership" - ], - "fields": [ - { - "fieldname": "date", - "fieldtype": "Date", - "in_list_view": 1, - "label": "Date", - "reqd": 1 - }, - { - "fieldname": "amount", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Amount", - "reqd": 1 - }, - { - "fieldname": "invoice_id", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Invoice ID", - "options": "Sales Invoice", - "reqd": 1 - }, - { - "fieldname": "razorpay_payment_id", - "fieldtype": "Data", - "label": "Razorpay Payment ID" - }, - { - "fieldname": "membership", - "fieldtype": "Link", - "label": "Membership", - "options": "Membership" - }, - { - "fieldname": "column_break_4", - "fieldtype": "Column Break" - } - ], - "index_web_pages_for_search": 1, - "istable": 1, - "links": [], - "modified": "2021-02-15 16:35:10.777587", - "modified_by": "Administrator", - "module": "Regional", - "name": "Tax Exemption 80G Certificate Detail", - "owner": "Administrator", - "permissions": [], - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py deleted file mode 100644 index bb7f07f688..0000000000 --- a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -# import frappe -from frappe.model.document import Document - - -class TaxExemption80GCertificateDetail(Document): - pass diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 074bd527e2..12b10bb4d9 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -53,10 +53,7 @@ def create_hsn_codes(data, code_field): hsn_code.description = d["description"] hsn_code.hsn_code = d[code_field] hsn_code.name = d[code_field] - try: - hsn_code.db_insert() - except frappe.DuplicateEntryError: - pass + hsn_code.db_insert(ignore_if_duplicate=True) def add_custom_roles_for_reports(): for report_name in ('GST Sales Register', 'GST Purchase Register', @@ -114,7 +111,7 @@ def add_permissions(): def add_print_formats(): frappe.reload_doc("regional", "print_format", "gst_tax_invoice") - frappe.reload_doc("accounts", "print_format", "gst_pos_invoice") + frappe.reload_doc("selling", "print_format", "gst_pos_invoice") frappe.reload_doc("accounts", "print_format", "GST E-Invoice") frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0) @@ -610,15 +607,6 @@ def get_custom_fields(): dict(fieldname='hra_column_break', fieldtype='Column Break', insert_after='hra_component'), dict(fieldname='arrear_component', label='Arrear Component', fieldtype='Link', options='Salary Component', insert_after='hra_column_break'), - dict(fieldname='non_profit_section', label='Non Profit Settings', - fieldtype='Section Break', insert_after='arrear_component', collapsible=1), - dict(fieldname='company_80g_number', label='80G Number', - fieldtype='Data', insert_after='non_profit_section'), - dict(fieldname='with_effect_from', label='80G With Effect From', - fieldtype='Date', insert_after='company_80g_number'), - dict(fieldname='non_profit_column_break', fieldtype='Column Break', insert_after='with_effect_from'), - dict(fieldname='pan_details', label='PAN Number', - fieldtype='Data', insert_after='non_profit_column_break') ], 'Employee Tax Exemption Declaration':[ dict(fieldname='hra_section', label='HRA Exemption', @@ -713,22 +701,6 @@ def get_custom_fields(): 'mandatory_depends_on': 'eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)' } ], - 'Member': [ - { - 'fieldname': 'pan_number', - 'label': 'PAN Details', - 'fieldtype': 'Data', - 'insert_after': 'email_id' - } - ], - 'Donor': [ - { - 'fieldname': 'pan_number', - 'label': 'PAN Details', - 'fieldtype': 'Data', - 'insert_after': 'email' - } - ], 'Finance Book': [ { 'fieldname': 'for_income_tax', diff --git a/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json b/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json deleted file mode 100644 index a8da0bd209..0000000000 --- a/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "absolute_value": 0, - "align_labels_right": 0, - "creation": "2021-02-22 00:17:33.878581", - "css": ".details {\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n line-height: 150%;\n}\n\n.certificate-footer {\n font-size: 15px;\n font-family: Tahoma, sans-serif;\n line-height: 140%;\n margin-top: 120px;\n}\n\n.company-address {\n color: #666666;\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n}", - "custom_format": 1, - "default_print_language": "en", - "disabled": 0, - "doc_type": "Tax Exemption 80G Certificate", - "docstatus": 0, - "doctype": "Print Format", - "font": "Default", - "html": "{% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n{%- endif %}\n\n
\n

{{ doc.company }} 80G Donor Certificate

\n
\n

\n\n
\n

{{ _(\"Certificate No. : \") }} {{ doc.name }}

\n

\n \t{{ _(\"Date\") }} : {{ doc.get_formatted(\"date\") }}
\n

\n

\n \n
\n\n This is to confirm that the {{ doc.company }} received an amount of {{doc.get_formatted(\"amount\")}}\n from {{ doc.donor_name }}\n {% if doc.pan_number -%}\n bearing PAN Number {{ doc.member_pan_number }}\n {%- endif %}\n\n via the Mode of Payment {{doc.mode_of_payment}}\n\n {% if doc.razorpay_payment_id -%}\n bearing RazorPay Payment ID {{ doc.razorpay_payment_id }}\n {%- endif %}\n\n on {{ doc.get_formatted(\"date_of_donation\") }}\n

\n \n

\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n

\n\n
\n
\n\n

\n

{{doc.company_address_display }}

\n\n", - "idx": 0, - "line_breaks": 0, - "modified": "2021-02-22 00:20:08.516600", - "modified_by": "Administrator", - "module": "Regional", - "name": "80G Certificate for Donation", - "owner": "Administrator", - "print_format_builder": 0, - "print_format_type": "Jinja", - "raw_printing": 0, - "show_section_headings": 0, - "standard": "Yes" -} \ No newline at end of file diff --git a/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py b/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json b/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json deleted file mode 100644 index f1b15aab29..0000000000 --- a/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "absolute_value": 0, - "align_labels_right": 0, - "creation": "2021-02-15 16:53:55.026611", - "css": ".details {\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n line-height: 150%;\n}\n\n.certificate-footer {\n font-size: 15px;\n font-family: Tahoma, sans-serif;\n line-height: 140%;\n margin-top: 120px;\n}\n\n.company-address {\n color: #666666;\n font-size: 15px;\n font-family: Tahoma, sans-serif;;\n}", - "custom_format": 1, - "default_print_language": "en", - "disabled": 0, - "doc_type": "Tax Exemption 80G Certificate", - "docstatus": 0, - "doctype": "Print Format", - "font": "Default", - "html": "{% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n{%- endif %}\n\n
\n

{{ doc.company }} Members 80G Donor Certificate

\n

Financial Cycle {{ doc.fiscal_year }}

\n
\n

\n\n
\n

{{ _(\"Certificate No. : \") }} {{ doc.name }}

\n

\n \t{{ _(\"Date\") }} : {{ doc.get_formatted(\"date\") }}
\n

\n

\n \n
\n This is to confirm that the {{ doc.company }} received a total amount of {{doc.get_formatted(\"total\")}}\n from {{ doc.member_name }}\n {% if doc.pan_number -%}\n bearing PAN Number {{ doc.member_pan_number }}\n {%- endif %}\n as per the payment details given below:\n \n

\n \n \t\n \t\t\n \t\t\t\n \t\t\t\n \t\t\t\n \t\t\n \t\n \t\n \t\t{%- for payment in doc.payments -%}\n \t\t\n \t\t\t\n \t\t\t\n \t\t\t\n \t\t\n \t\t{%- endfor -%}\n \t\n
{{ _(\"Date\") }}{{ _(\"Amount\") }}{{ _(\"Invoice ID\") }}
{{ payment.date }} {{ payment.get_formatted(\"amount\") }}{{ payment.invoice_id }}
\n \n
\n \n

\n We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n

\n\n
\n
\n\n

\n

{{doc.company_address_display }}

\n\n", - "idx": 0, - "line_breaks": 0, - "modified": "2021-02-21 23:29:00.778973", - "modified_by": "Administrator", - "module": "Regional", - "name": "80G Certificate for Membership", - "owner": "Administrator", - "print_format_builder": 0, - "print_format_type": "Jinja", - "raw_printing": 0, - "show_section_headings": 0, - "standard": "Yes" -} \ No newline at end of file diff --git a/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py b/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js index 4d75e6ef1b..1e9f6d7d92 100644 --- a/erpnext/selling/page/point_of_sale/pos_payment.js +++ b/erpnext/selling/page/point_of_sale/pos_payment.js @@ -170,17 +170,20 @@ erpnext.PointOfSale.Payment = class { }); frappe.ui.form.on('POS Invoice', 'coupon_code', (frm) => { - if (!frm.doc.ignore_pricing_rule) { - if (frm.doc.coupon_code) { - frappe.run_serially([ - () => frm.doc.ignore_pricing_rule=1, - () => frm.trigger('ignore_pricing_rule'), - () => frm.doc.ignore_pricing_rule=0, - () => frm.trigger('apply_pricing_rule'), - () => frm.save(), - () => this.update_totals_section(frm.doc) - ]); - } + if (!frm.doc.ignore_pricing_rule && frm.doc.coupon_code) { + frappe.run_serially([ + () => frm.doc.ignore_pricing_rule=1, + () => frm.trigger('ignore_pricing_rule'), + () => frm.doc.ignore_pricing_rule=0, + () => frm.trigger('apply_pricing_rule'), + () => frm.save(), + () => this.update_totals_section(frm.doc) + ]); + } else if (frm.doc.ignore_pricing_rule && frm.doc.coupon_code) { + frappe.show_alert({ + message: __("Ignore Pricing Rule is enabled. Cannot apply coupon code."), + indicator: "orange" + }); } }); diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index cd2738aeaa..cefa0f3887 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -195,10 +195,8 @@ def install(country=None): {'doctype': "Party Type", "party_type": "Customer", "account_type": "Receivable"}, {'doctype': "Party Type", "party_type": "Supplier", "account_type": "Payable"}, {'doctype': "Party Type", "party_type": "Employee", "account_type": "Payable"}, - {'doctype': "Party Type", "party_type": "Member", "account_type": "Receivable"}, {'doctype': "Party Type", "party_type": "Shareholder", "account_type": "Payable"}, {'doctype': "Party Type", "party_type": "Student", "account_type": "Receivable"}, - {'doctype': "Party Type", "party_type": "Donor", "account_type": "Receivable"}, {'doctype': "Opportunity Type", "name": _("Sales")}, {'doctype': "Opportunity Type", "name": _("Support")}, diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 4441bb9562..a4f2207f11 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -155,7 +155,7 @@ def insert_record(records): doc = frappe.new_doc(r.get("doctype")) doc.update(r) try: - doc.insert(ignore_permissions=True) + doc.insert(ignore_permissions=True, ignore_if_duplicate=True) except frappe.DuplicateEntryError as e: # pass DuplicateEntryError and continue if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name: diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index baa03024af..613dd3f14d 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -433,14 +433,13 @@ def create_price_list_for_batch(item_code, batch, rate): def make_new_batch(**args): args = frappe._dict(args) - try: + if frappe.db.exists("Batch", args.batch_id): + batch = frappe.get_doc("Batch", args.batch_id) + else: batch = frappe.get_doc({ "doctype": "Batch", "batch_id": args.batch_id, "item": args.item_code, }).insert() - except frappe.DuplicateEntryError: - batch = frappe.get_doc("Batch", args.batch_id) - return batch diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index b9e8b3f2f1..494fb3b8bb 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -398,6 +398,7 @@ class Item(Document): if merge: self.validate_properties_before_merge(new_name) + self.validate_duplicate_product_bundles_before_merge(old_name, new_name) self.validate_duplicate_website_item_before_merge(old_name, new_name) def after_rename(self, old_name, new_name, merge): @@ -462,6 +463,20 @@ class Item(Document): msg += ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]) frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError) + def validate_duplicate_product_bundles_before_merge(self, old_name, new_name): + "Block merge if both old and new items have product bundles." + old_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name}) + new_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": new_name}) + + if old_bundle and new_bundle: + bundle_link = get_link_to_form("Product Bundle", old_bundle) + old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) + + msg = _("Please delete Product Bundle {0}, before merging {1} into {2}").format( + bundle_link, old_name, new_name + ) + frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError) + def validate_duplicate_website_item_before_merge(self, old_name, new_name): """ Block merge if both old and new items have website items against them. @@ -479,8 +494,9 @@ class Item(Document): old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0] web_item_link = get_link_to_form("Website Item", old_web_item) + old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) - msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} and {new_name}" + msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} into {new_name}" frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError) def set_last_purchase_rate(self, new_name): diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index fd4df42187..9491e17259 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -15,6 +15,7 @@ from erpnext.controllers.item_variant import ( get_variant, ) from erpnext.stock.doctype.item.item import ( + DataValidationError, InvalidBarcode, StockExistsForTemplate, get_item_attribute, @@ -388,6 +389,26 @@ class TestItem(ERPNextTestCase): self.assertTrue(frappe.db.get_value("Bin", {"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"})) + def test_item_merging_with_product_bundle(self): + from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle + + create_item("Test Item Bundle Item 1", is_stock_item=False) + create_item("Test Item Bundle Item 2", is_stock_item=False) + create_item("Test Item inside Bundle") + bundle_items = ["Test Item inside Bundle"] + + # make bundles for both items + bundle1 = make_product_bundle("Test Item Bundle Item 1", bundle_items, qty=2) + make_product_bundle("Test Item Bundle Item 2", bundle_items, qty=2) + + with self.assertRaises(DataValidationError): + frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True) + + bundle1.delete() + frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True) + + self.assertFalse(frappe.db.exists("Item", "Test Item Bundle Item 1")) + def test_uom_conversion_factor(self): if frappe.db.exists('Item', 'Test Item UOM'): frappe.delete_doc('Item', 'Test Item UOM') diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 5c9da3a205..324ca7ac59 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -629,6 +629,12 @@ frappe.ui.form.on('Stock Entry Detail', { frm.events.set_serial_no(frm, cdt, cdn, () => { frm.events.get_warehouse_details(frm, cdt, cdn); }); + + // set allow_zero_valuation_rate to 0 if s_warehouse is selected. + let item = frappe.get_doc(cdt, cdn); + if (item.s_warehouse) { + item.allow_zero_valuation_rate = 0; + } }, t_warehouse: function(frm, cdt, cdn) { diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 6c6513beff..c5afa49166 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -44,6 +44,7 @@ def get_sle(**args): class TestStockEntry(ERPNextTestCase): def tearDown(self): + frappe.db.rollback() frappe.set_user("Administrator") frappe.db.set_value("Manufacturing Settings", None, "material_consumption", "0") @@ -565,6 +566,7 @@ class TestStockEntry(ERPNextTestCase): st1.set_stock_entry_type() st1.insert() st1.submit() + st1.cancel() frappe.set_user("Administrator") remove_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com") @@ -689,6 +691,8 @@ class TestStockEntry(ERPNextTestCase): bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", "is_default": 1, "docstatus": 1}) + make_item_variant() # make variant of _Test Variant Item if absent + work_order = frappe.new_doc("Work Order") work_order.update({ "company": "_Test Company", @@ -1023,13 +1027,10 @@ class TestStockEntry(ERPNextTestCase): # Check if FG cost is calculated based on RM total cost # RM total cost = 200, FG rate = 200/4(FG qty) = 50 - self.assertEqual(se.items[1].basic_rate, 50) + self.assertEqual(se.items[1].basic_rate, flt(se.items[0].basic_rate/4)) self.assertEqual(se.value_difference, 0.0) self.assertEqual(se.total_incoming_value, se.total_outgoing_value) - # teardown - se.delete() - @change_settings("Stock Settings", {"allow_negative_stock": 0}) def test_future_negative_sle(self): # Initialize item, batch, warehouse, opening qty diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index df65706c39..83aed904dd 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -1,7 +1,7 @@ { "actions": [], "autoname": "hash", - "creation": "2013-03-29 18:22:12", + "creation": "2022-02-05 00:17:49.860824", "doctype": "DocType", "document_type": "Other", "editable_grid": 1, @@ -340,13 +340,13 @@ "label": "More Information" }, { - "allow_on_submit": 1, "default": "0", "fieldname": "allow_zero_valuation_rate", "fieldtype": "Check", "label": "Allow Zero Valuation Rate", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "read_only_depends_on": "eval:doc.s_warehouse" }, { "allow_on_submit": 1, @@ -556,12 +556,14 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-22 16:47:11.268975", + "modified": "2022-02-26 00:51:24.963653", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], "sort_field": "modified", - "sort_order": "ASC" + "sort_order": "ASC", + "states": [] } \ No newline at end of file diff --git a/erpnext/stock/report/test_reports.py b/erpnext/stock/report/test_reports.py index 525af40b41..76c20798bf 100644 --- a/erpnext/stock/report/test_reports.py +++ b/erpnext/stock/report/test_reports.py @@ -73,10 +73,11 @@ class TestReports(unittest.TestCase): def test_execute_all_stock_reports(self): """Test that all script report in stock modules are executable with supported filters""" for report, filter in REPORT_FILTER_TEST_CASES: - execute_script_report( - report_name=report, - module="Stock", - filters=filter, - default_filters=DEFAULT_FILTERS, - optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, - ) + with self.subTest(report=report): + execute_script_report( + report_name=report, + module="Stock", + filters=filter, + default_filters=DEFAULT_FILTERS, + optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None, + ) diff --git a/erpnext/templates/includes/navbar/navbar_items.html b/erpnext/templates/includes/navbar/navbar_items.html index 327552117b..d7adae562e 100644 --- a/erpnext/templates/includes/navbar/navbar_items.html +++ b/erpnext/templates/includes/navbar/navbar_items.html @@ -13,7 +13,7 @@