Merge pull request #22946 from deepeshgarg007/gst_export_wopay
fix: GSTR 1 report for exports without payment of Tax
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index c6de641..164f120 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -244,6 +244,8 @@
super(Account, self).on_trash(True)
+@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select name from tabAccount
where is_group = 1 and docstatus != 2 and company = %s
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
index 1bf9196..0e3b24c 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
@@ -225,7 +225,7 @@
account['parent_account'] = parent
account['expandable'] = True if identify_is_group(child) else False
- account['value'] = (child.get('account_number') + ' - ' + account_name) \
+ account['value'] = (cstr(child.get('account_number')).strip() + ' - ' + account_name) \
if child.get('account_number') else account_name
accounts.append(account)
_import_accounts(child, account['value'])
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 8ca8b71..b2e8b09 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -225,7 +225,7 @@
"idx": 1,
"issingle": 1,
"links": [],
- "modified": "2020-06-22 20:13:26.043092",
+ "modified": "2020-08-03 20:13:26.043092",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 6fec3ab..76d82e7 100644
--- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -60,12 +60,12 @@
""".format(condition=condition), {"account": self.account, "from":self.from_date,
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
- pos_entries = []
+ pos_sales_invoices, pos_purchase_invoices = [], []
if self.include_pos_transactions:
- pos_entries = frappe.db.sql("""
+ pos_sales_invoices = 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,
+ si.posting_date, si.customer as against_account, sip.clearance_date,
account.account_currency, 0 as credit
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
where
@@ -75,7 +75,20 @@
si.posting_date ASC, si.name DESC
""", {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
- entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
+ pos_purchase_invoices = frappe.db.sql("""
+ select
+ "Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
+ pi.posting_date, pi.supplier as against_account, pi.clearance_date,
+ account.account_currency, 0 as debit
+ from `tabPurchase Invoice` pi, `tabAccount` account
+ where
+ pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
+ and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
+ order by
+ pi.posting_date ASC, pi.name DESC
+ """, {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
+
+ entries = sorted(list(payment_entries) + list(journal_entries + list(pos_sales_invoices) + list(pos_purchase_invoices)),
key=lambda k: k['posting_date'] or getdate(nowdate()))
self.set('payment_entries', [])
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index c563368..9909c6c 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -44,6 +44,19 @@
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
+
+ if(frm.doc.docstatus > 0) {
+ frm.add_custom_button(__('Ledger'), function() {
+ frappe.route_options = {
+ "voucher_no": frm.doc.name,
+ "from_date": frm.doc.posting_date,
+ "to_date": frm.doc.posting_date,
+ "company": frm.doc.company,
+ "show_cancelled_entries": frm.doc.docstatus === 2
+ };
+ frappe.set_route("query-report", "General Ledger");
+ }, __('View'));
+ }
},
overdue_days: function (frm) {
frappe.db.get_value(
@@ -125,9 +138,9 @@
},
calculate_interest_and_amount: function (frm) {
const interest_per_year = frm.doc.outstanding_amount * frm.doc.rate_of_interest / 100;
- const interest_amount = interest_per_year / 365 * frm.doc.overdue_days || 0;
- const dunning_amount = interest_amount + frm.doc.dunning_fee;
- const grand_total = frm.doc.outstanding_amount + dunning_amount;
+ const interest_amount = flt((interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0, precision('interest_amount'));
+ const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision('dunning_amount'));
+ const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision('grand_total'));
frm.set_value("interest_amount", interest_amount);
frm.set_value("dunning_amount", dunning_amount);
frm.set_value("grand_total", grand_total);
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index b3eddf5..d55bfd1 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -29,10 +29,10 @@
"company_address_display",
"section_break_6",
"dunning_type",
- "interest_amount",
+ "dunning_fee",
"column_break_8",
"rate_of_interest",
- "dunning_fee",
+ "interest_amount",
"section_break_12",
"dunning_amount",
"grand_total",
@@ -215,7 +215,7 @@
},
{
"default": "0",
- "fetch_from": "dunning_type.interest_rate",
+ "fetch_from": "dunning_type.rate_of_interest",
"fetch_if_empty": 1,
"fieldname": "rate_of_interest",
"fieldtype": "Float",
@@ -315,7 +315,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-07-21 18:20:23.512151",
+ "modified": "2020-08-03 18:55:43.683053",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning",
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 0be6a48..1a6dbed 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -6,7 +6,7 @@
import frappe
import json
from six import string_types
-from frappe.utils import getdate, get_datetime, rounded, flt
+from frappe.utils import getdate, get_datetime, rounded, flt, cint
from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@@ -27,11 +27,11 @@
amounts = calculate_interest_and_amount(
self.posting_date, self.outstanding_amount, self.rate_of_interest, self.dunning_fee, self.overdue_days)
if self.interest_amount != amounts.get('interest_amount'):
- self.interest_amount = amounts.get('interest_amount')
+ self.interest_amount = flt(amounts.get('interest_amount'), self.precision('interest_amount'))
if self.dunning_amount != amounts.get('dunning_amount'):
- self.dunning_amount = amounts.get('dunning_amount')
+ self.dunning_amount = flt(amounts.get('dunning_amount'), self.precision('dunning_amount'))
if self.grand_total != amounts.get('grand_total'):
- self.grand_total = amounts.get('grand_total')
+ self.grand_total = flt(amounts.get('grand_total'), self.precision('grand_total'))
def on_submit(self):
self.make_gl_entries()
@@ -47,10 +47,13 @@
gl_entries = []
invoice_fields = ["project", "cost_center", "debit_to", "party_account_currency", "conversion_rate", "cost_center"]
inv = frappe.db.get_value("Sales Invoice", self.sales_invoice, invoice_fields, as_dict=1)
+
accounting_dimensions = get_accounting_dimensions()
invoice_fields.extend(accounting_dimensions)
+
dunning_in_company_currency = flt(self.dunning_amount * inv.conversion_rate)
default_cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
+
gl_entries.append(
self.get_gl_dict({
"account": inv.debit_to,
@@ -90,10 +93,10 @@
def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
interest_amount = 0
+ grand_total = 0
if rate_of_interest:
- interest_per_year = rounded(flt(outstanding_amount) * flt(rate_of_interest))/100
- interest_amount = (
- interest_per_year / days_in_year(get_datetime(posting_date).year)) * int(overdue_days)
+ interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100
+ interest_amount = (interest_per_year * cint(overdue_days)) / 365
grand_total = flt(outstanding_amount) + flt(interest_amount) + flt(dunning_fee)
dunning_amount = flt(interest_amount) + flt(dunning_fee)
return {
diff --git a/erpnext/accounts/doctype/dunning/dunning_dashboard.py b/erpnext/accounts/doctype/dunning/dunning_dashboard.py
new file mode 100644
index 0000000..19a73dd
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/dunning_dashboard.py
@@ -0,0 +1,17 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'dunning',
+ 'non_standard_fieldnames': {
+ 'Journal Entry': 'reference_name',
+ 'Payment Entry': 'reference_name'
+ },
+ 'transactions': [
+ {
+ 'label': _('Payment'),
+ 'items': ['Payment Entry', 'Journal Entry']
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index cfdae93..dda1708 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -841,13 +841,33 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
- return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
- from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
- where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
- and (jv_detail.reference_type is null or jv_detail.reference_type = '')
- and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(searchfield),
- (filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
+ if not frappe.db.has_column('Journal Entry', searchfield):
+ return []
+
+ return frappe.db.sql("""
+ SELECT jv.name, jv.posting_date, jv.user_remark
+ FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
+ WHERE jv_detail.parent = jv.name
+ AND jv_detail.account = %(account)s
+ AND IFNULL(jv_detail.party, '') = %(party)s
+ AND (
+ jv_detail.reference_type IS NULL
+ OR jv_detail.reference_type = ''
+ )
+ AND jv.docstatus = 1
+ AND jv.`{0}` LIKE %(txt)s
+ ORDER BY jv.name DESC
+ LIMIT %(offset)s, %(limit)s
+ """.format(searchfield), dict(
+ account=filters.get("account"),
+ party=cstr(filters.get("party")),
+ txt="%{0}%".format(txt),
+ offset=start,
+ limit=page_len
+ )
+ )
@frappe.whitelist()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index adfaade..9fc44bc 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -42,7 +42,8 @@
frm.set_query("bank_account", function() {
return {
filters: {
- is_company_account: 1
+ is_company_account: 1,
+ company: frm.doc.company
}
}
});
@@ -1049,4 +1050,4 @@
});
}
},
-})
\ No newline at end of file
+})
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 9df8655..842c64f 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -897,7 +897,7 @@
total_amount = ref_doc.get("grand_total")
exchange_rate = 1
outstanding_amount = ref_doc.get("outstanding_amount")
- if reference_doctype == "Dunning":
+ elif reference_doctype == "Dunning":
total_amount = ref_doc.get("dunning_amount")
exchange_rate = 1
outstanding_amount = ref_doc.get("dunning_amount")
@@ -1101,7 +1101,7 @@
'outstanding_amount': doc.get('dunning_amount'),
'allocated_amount': doc.get('dunning_amount')
})
- else:
+ else:
pe.append("references", {
'reference_doctype': dt,
'reference_name': dn,
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py
index 4702e58..e5880aa 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/payment_order.py
@@ -27,6 +27,7 @@
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
where parent = %(parent)s and mode_of_payment like %(txt)s
@@ -38,6 +39,7 @@
})
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
where parent = %(parent)s and supplier like %(txt)s and
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
index 8eb0a22..9899219 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -24,7 +24,7 @@
if user:
frappe.throw(_("POS Closing Entry {} against {} between selected period"
.format(frappe.bold("already exists"), frappe.bold(self.user))), title=_("Invalid Period"))
-
+
if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
@@ -41,6 +41,7 @@
{"data": self, "currency": currency})
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'])
return [c['user'] for c in cashiers_list]
@@ -48,12 +49,12 @@
@frappe.whitelist()
def get_pos_invoices(start, end, user):
data = frappe.db.sql("""
- select
+ select
name, timestamp(posting_date, posting_time) as "timestamp"
- from
+ from
`tabPOS Invoice`
- where
- owner = %s and docstatus = 1 and
+ where
+ owner = %s and docstatus = 1 and
(consolidated_invoice is NULL or consolidated_invoice = '')
""", (user), as_dict=1)
@@ -101,7 +102,7 @@
for t in d.taxes:
existing_tax = [tx for tx in taxes if tx.account_head == t.account_head and tx.rate == t.rate]
if existing_tax:
- existing_tax[0].amount += flt(t.tax_amount);
+ existing_tax[0].amount += flt(t.tax_amount);
else:
taxes.append(frappe._dict({
'account_head': t.account_head,
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 8655b4b..789b4c3 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -105,6 +105,7 @@
return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
user = frappe.session['user']
company = filters.get('company') or frappe.defaults.get_user_default('company')
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index d90ae28..cff7d5b 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -433,14 +433,14 @@
return doc
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
items = [filters.get('value')]
if filters.get('apply_on') != 'Item Code':
field = frappe.scrub(filters.get('apply_on'))
+ items = [d.name for d in frappe.db.get_all("Item", filters={field: filters.get('value')})]
- items = frappe.db.sql_list("""select name
- from `tabItem` where {0} = %s""".format(field), filters.get('value'))
-
- return frappe.get_all('UOM Conversion Detail',
- filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
- fields = ["distinct uom"], as_list=1)
+ return frappe.get_all('UOM Conversion Detail', filters={
+ 'parent': ('in', items),
+ 'uom': ("like", "{0}%".format(txt))
+ }, fields = ["distinct uom"], as_list=1)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index df77dc8..2e91c8e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -969,8 +969,10 @@
{
"fieldname": "clearance_date",
"fieldtype": "Date",
- "hidden": 1,
- "label": "Clearance Date"
+ "label": "Clearance Date",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
},
{
"fieldname": "col_br_payments",
@@ -1332,7 +1334,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2020-07-24 09:46:40.405463",
+ "modified": "2020-08-03 12:46:01.411074",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
index 4a8fcc0..f106928 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -18,7 +18,7 @@
'transactions': [
{
'label': _('Payment'),
- 'items': ['Payment Entry', 'Payment Request', 'Journal Entry', 'Invoice Discounting']
+ 'items': ['Payment Entry', 'Payment Request', 'Journal Entry', 'Invoice Discounting', 'Dunning']
},
{
'label': _('Reference'),
diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
index 2f9d381..5ab46b7 100644
--- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
+++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
@@ -64,6 +64,7 @@
"fieldname": "clearance_date",
"fieldtype": "Date",
"label": "Clearance Date",
+ "no_copy": 1,
"print_hide": 1,
"read_only": 1
},
@@ -78,7 +79,7 @@
],
"istable": 1,
"links": [],
- "modified": "2020-05-05 16:51:20.091441",
+ "modified": "2020-08-03 12:45:39.986598",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Payment",
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py
index f41f08a..811fc35 100644
--- a/erpnext/accounts/doctype/subscription/test_subscription.py
+++ b/erpnext/accounts/doctype/subscription/test_subscription.py
@@ -7,8 +7,8 @@
import frappe
from erpnext.accounts.doctype.subscription.subscription import get_prorata_factor
-from frappe.utils.data import nowdate, add_days, add_to_date, add_months, date_diff, flt, get_date_str
-
+from frappe.utils.data import (nowdate, add_days, add_to_date, add_months, date_diff, flt, get_date_str,
+ get_first_day, get_last_day)
def create_plan():
if not frappe.db.exists('Subscription Plan', '_Test Plan Name'):
@@ -68,14 +68,14 @@
subscription.party_type = 'Customer'
subscription.party = '_Test Customer'
subscription.trial_period_start = nowdate()
- subscription.trial_period_end = add_days(nowdate(), 30)
+ subscription.trial_period_end = add_months(nowdate(), 1)
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
subscription.save()
self.assertEqual(subscription.trial_period_start, nowdate())
- self.assertEqual(subscription.trial_period_end, add_days(nowdate(), 30))
+ self.assertEqual(subscription.trial_period_end, add_months(nowdate(), 1))
self.assertEqual(add_days(subscription.trial_period_end, 1), get_date_str(subscription.current_invoice_start))
- self.assertEqual(add_days(subscription.current_invoice_start, 30), get_date_str(subscription.current_invoice_end))
+ self.assertEqual(add_to_date(subscription.current_invoice_start, months=1, days=-1), get_date_str(subscription.current_invoice_end))
self.assertEqual(subscription.invoices, [])
self.assertEqual(subscription.status, 'Trialling')
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 7df090b..ce6baa6 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -290,6 +290,7 @@
return []
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
if not account:
@@ -319,6 +320,7 @@
)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
@@ -355,6 +357,7 @@
)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
SELECT
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 66aa180..59117c8 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -643,8 +643,10 @@
account_type = "Receivable" if self.party_type == "Customer" else "Payable"
accounts = [d.name for d in frappe.get_all("Account",
filters={"account_type": account_type, "company": self.filters.company})]
- conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
- values += accounts
+
+ if accounts:
+ conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
+ values += accounts
def add_customer_filters(self, conditions, values):
if self.filters.get("customer_group"):
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 824b2f2..51ac7cf 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -122,7 +122,7 @@
cost_center = frappe.form_dict.get("cost_center")
- cond = []
+ cond = ["is_cancelled=0"]
if date:
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else:
@@ -206,7 +206,7 @@
return flt(bal)
def get_count_on(account, fieldname, date):
- cond = []
+ cond = ["is_cancelled=0"]
if date:
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else:
diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
index 1869a29..60c528b 100644
--- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
@@ -106,6 +106,7 @@
maintenance_log.save()
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_team_members(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.get_values('Maintenance Team Member', { 'parent': filters.get("maintenance_team") })
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
index f169f01..148357f 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
@@ -41,6 +41,7 @@
asset_maintenance_doc.save()
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters):
asset_maintenance_tasks = frappe.db.get_values('Asset Maintenance Task', {'parent':filters.get("asset_maintenance")}, 'maintenance_task')
return asset_maintenance_tasks
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 502dbba..4201e0b 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1084,7 +1084,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2020-07-18 05:09:33.800633",
+ "modified": "2020-07-31 14:13:44.610190",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@@ -1135,5 +1135,5 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
- "title_field": "title"
+ "title_field": "supplier"
}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 4b85230..b54a585 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -207,6 +207,7 @@
return list_context
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 31e3498..babc5bd 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -12,6 +12,7 @@
# searches for active employees
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def employee_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("Employee", ["name", "employee_name"])
@@ -42,6 +43,7 @@
# searches for leads which are not converted
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def lead_query(doctype, txt, searchfield, start, page_len, filters):
fields = get_fields("Lead", ["name", "lead_name", "company_name"])
@@ -72,6 +74,7 @@
# searches for customer
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def customer_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
cust_master_name = frappe.defaults.get_user_default("cust_master_name")
@@ -110,8 +113,10 @@
# searches for supplier
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
+
if supp_master_name == "Supplier Name":
fields = ["name", "supplier_group"]
else:
@@ -142,32 +147,49 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
company_currency = erpnext.get_company_currency(filters.get('company'))
- tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
- where tabAccount.docstatus!=2
- and account_type in (%s)
- and is_group = 0
- and company = %s
- and account_currency = %s
- and `%s` LIKE %s
- order by idx desc, name
- limit %s, %s""" %
- (", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
- tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
- start, page_len]))
+ def get_accounts(with_account_type_filter):
+ account_type_condition = ''
+ if with_account_type_filter:
+ account_type_condition = "AND account_type in %(account_types)s"
+
+ accounts = frappe.db.sql("""
+ SELECT name, parent_account
+ FROM `tabAccount`
+ WHERE `tabAccount`.docstatus!=2
+ {account_type_condition}
+ AND is_group = 0
+ AND company = %(company)s
+ AND account_currency = %(currency)s
+ AND `{searchfield}` LIKE %(txt)s
+ ORDER BY idx DESC, name
+ LIMIT %(offset)s, %(limit)s
+ """.format(account_type_condition=account_type_condition, searchfield=searchfield),
+ dict(
+ account_types=filters.get("account_type"),
+ company=filters.get("company"),
+ currency=company_currency,
+ txt="%{}%".format(txt),
+ offset=start,
+ limit=page_len
+ )
+ )
+
+ return accounts
+
+ tax_accounts = get_accounts(True)
+
if not tax_accounts:
- tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
- where tabAccount.docstatus!=2 and is_group = 0
- and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
- % ("%s", "%s", searchfield, "%s", "%s", "%s"),
- (filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
+ tax_accounts = get_accounts(False)
return tax_accounts
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
@@ -215,7 +237,6 @@
idx desc,
name, item_name
limit %(start)s, %(page_len)s """.format(
- key=searchfield,
columns=columns,
scond=searchfields,
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
@@ -231,6 +252,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def bom(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("BOM", ["name", "item"])
@@ -258,6 +280,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
cond = ''
if filters.get('customer'):
@@ -285,6 +308,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
@@ -315,6 +339,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
cond = ""
if filters.get("posting_date"):
@@ -373,6 +398,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
filter_list = []
@@ -395,8 +421,8 @@
fields = ["name", "parent_account"],
limit_start=start, limit_page_length=page_len, as_list=True)
-
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
from `tabBlanket Order` bo, `tabBlanket Order Item` boi
@@ -413,6 +439,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
@@ -439,6 +466,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
@@ -463,6 +491,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
# Should be used when item code is passed in filters.
conditions, bin_conditions = [], []
@@ -506,6 +535,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
query = """select batch_id from `tabBatch`
where disabled = 0
@@ -519,6 +549,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
item_filters = [
['manufacturer', 'like', '%' + txt + '%'],
@@ -537,6 +568,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
query = """
select pr.name
@@ -551,6 +583,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
query = """
select pi.name
@@ -565,6 +598,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
diff --git a/erpnext/education/dashboard_chart/course_wise_enrollment/course_wise_enrollment.json b/erpnext/education/dashboard_chart/course_wise_enrollment/course_wise_enrollment.json
new file mode 100644
index 0000000..9c5f784
--- /dev/null
+++ b/erpnext/education/dashboard_chart/course_wise_enrollment/course_wise_enrollment.json
@@ -0,0 +1,31 @@
+{
+ "based_on": "",
+ "chart_name": "Course wise Enrollment",
+ "chart_type": "Group By",
+ "creation": "2020-07-23 18:24:38.214220",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Course Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Course Enrollment\",\"enrollment_date\",\"Timespan\",\"this year\",false]]",
+ "group_by_based_on": "course",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:50:32.490587",
+ "modified": "2020-07-27 17:54:09.829206",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course wise Enrollment",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/course_wise_student_count/course_wise_student_count.json b/erpnext/education/dashboard_chart/course_wise_student_count/course_wise_student_count.json
new file mode 100644
index 0000000..5441518
--- /dev/null
+++ b/erpnext/education/dashboard_chart/course_wise_student_count/course_wise_student_count.json
@@ -0,0 +1,31 @@
+{
+ "based_on": "",
+ "chart_name": "Course wise Student Count",
+ "chart_type": "Group By",
+ "creation": "2020-07-27 17:24:39.136163",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Course Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Course Enrollment\",\"enrollment_date\",\"Timespan\",\"this year\",false]]",
+ "group_by_based_on": "course",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:24:56.184236",
+ "modified": "2020-07-27 17:25:46.232846",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course wise Student Count",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/instructor_gender_diversity_ratio/instructor_gender_diversity_ratio.json b/erpnext/education/dashboard_chart/instructor_gender_diversity_ratio/instructor_gender_diversity_ratio.json
new file mode 100644
index 0000000..b7ee509
--- /dev/null
+++ b/erpnext/education/dashboard_chart/instructor_gender_diversity_ratio/instructor_gender_diversity_ratio.json
@@ -0,0 +1,31 @@
+{
+ "based_on": "",
+ "chart_name": "Instructor Gender Diversity Ratio",
+ "chart_type": "Group By",
+ "creation": "2020-07-23 18:35:02.544019",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Instructor",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Instructor\",\"status\",\"=\",\"Active\",false]]",
+ "group_by_based_on": "gender",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:50:32.783820",
+ "modified": "2020-07-27 17:55:41.595260",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Instructor Gender Diversity Ratio",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/program_enrollments/program_enrollments.json b/erpnext/education/dashboard_chart/program_enrollments/program_enrollments.json
new file mode 100644
index 0000000..2a4a4a3
--- /dev/null
+++ b/erpnext/education/dashboard_chart/program_enrollments/program_enrollments.json
@@ -0,0 +1,30 @@
+{
+ "based_on": "enrollment_date",
+ "chart_name": "Program Enrollments",
+ "chart_type": "Count",
+ "creation": "2020-07-23 18:27:53.641616",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Program Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Program Enrollment\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:50:32.203069",
+ "modified": "2020-07-27 17:51:59.022909",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program Enrollments",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Daily",
+ "timeseries": 1,
+ "timespan": "Last Month",
+ "type": "Line",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/program_wise_enrollment/program_wise_enrollment.json b/erpnext/education/dashboard_chart/program_wise_enrollment/program_wise_enrollment.json
new file mode 100644
index 0000000..2ba138e
--- /dev/null
+++ b/erpnext/education/dashboard_chart/program_wise_enrollment/program_wise_enrollment.json
@@ -0,0 +1,31 @@
+{
+ "based_on": "",
+ "chart_name": "Program wise Enrollment",
+ "chart_type": "Group By",
+ "creation": "2020-07-23 18:23:45.192748",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Program Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Program Enrollment\",\"docstatus\",\"=\",\"1\",false],[\"Program Enrollment\",\"enrollment_date\",\"Timespan\",\"this year\",false]]",
+ "group_by_based_on": "program",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:50:32.629321",
+ "modified": "2020-07-27 17:53:36.269098",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program wise Enrollment",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/program_wise_fee_collection/program_wise_fee_collection.json b/erpnext/education/dashboard_chart/program_wise_fee_collection/program_wise_fee_collection.json
new file mode 100644
index 0000000..38c1b6d
--- /dev/null
+++ b/erpnext/education/dashboard_chart/program_wise_fee_collection/program_wise_fee_collection.json
@@ -0,0 +1,28 @@
+{
+ "chart_name": "Program wise Fee Collection",
+ "chart_type": "Report",
+ "creation": "2020-08-05 16:19:53.398335",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"from_date\":\"frappe.datetime.add_months(frappe.datetime.get_today(), -1)\",\"to_date\":\"frappe.datetime.nowdate()\"}",
+ "filters_json": "{}",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-08-05 16:20:47.436847",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program wise Fee Collection",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Program wise Fee Collection",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 1,
+ "x_field": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/student_category_wise_program_enrollments/student_category_wise_program_enrollments.json b/erpnext/education/dashboard_chart/student_category_wise_program_enrollments/student_category_wise_program_enrollments.json
new file mode 100644
index 0000000..8887145
--- /dev/null
+++ b/erpnext/education/dashboard_chart/student_category_wise_program_enrollments/student_category_wise_program_enrollments.json
@@ -0,0 +1,31 @@
+{
+ "based_on": "",
+ "chart_name": "Student Category wise Program Enrollments",
+ "chart_type": "Group By",
+ "creation": "2020-07-27 17:37:47.116446",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Program Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Program Enrollment\",\"enrollment_date\",\"Timespan\",\"this year\",false],[\"Program Enrollment\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_based_on": "student_category",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-27 17:46:54.901911",
+ "modified": "2020-07-27 17:47:21.370866",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Category wise Program Enrollments",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/dashboard_chart/student_gender_diversity_ratio/student_gender_diversity_ratio.json b/erpnext/education/dashboard_chart/student_gender_diversity_ratio/student_gender_diversity_ratio.json
new file mode 100644
index 0000000..ce602d2
--- /dev/null
+++ b/erpnext/education/dashboard_chart/student_gender_diversity_ratio/student_gender_diversity_ratio.json
@@ -0,0 +1,30 @@
+{
+ "based_on": "",
+ "chart_name": "Student Gender Diversity Ratio",
+ "chart_type": "Group By",
+ "creation": "2020-07-23 18:12:15.972123",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Student",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Student\",\"enabled\",\"=\",1,false]]",
+ "group_by_based_on": "gender",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-23 18:12:21.606772",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Gender Diversity Ratio",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "value_based_on": "",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json
index b341ec4..77ee8ec 100644
--- a/erpnext/education/desk_page/education/education.json
+++ b/erpnext/education/desk_page/education/education.json
@@ -2,18 +2,13 @@
"cards": [
{
"hidden": 0,
- "label": "Tools",
- "links": "[\n {\n \"label\": \"Student Attendance Tool\",\n \"name\": \"Student Attendance Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result Tool\",\n \"name\": \"Assessment Result Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group Creation Tool\",\n \"name\": \"Student Group Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment Tool\",\n \"name\": \"Program Enrollment Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]"
+ "label": "Student and Instructor",
+ "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Guardian\",\n \"name\": \"Guardian\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group\",\n \"name\": \"Student Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Log\",\n \"name\": \"Student Log\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
- "label": "Other Reports",
- "links": "[\n {\n \"dependencies\": [\n \"Program Enrollment\"\n ],\n \"doctype\": \"Program Enrollment\",\n \"is_query_report\": true,\n \"label\": \"Student and Guardian Contact Details\",\n \"name\": \"Student and Guardian Contact Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Monthly Attendance Sheet\",\n \"name\": \"Student Monthly Attendance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Student Fee Collection\",\n \"name\": \"Student Fee Collection\",\n \"type\": \"report\"\n }\n]"
- },
- {
- "hidden": 0,
- "label": "Settings",
- "links": "[\n {\n \"label\": \"Student Category\",\n \"name\": \"Student Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Batch Name\",\n \"name\": \"Student Batch Name\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Grading Scale\",\n \"name\": \"Grading Scale\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Term\",\n \"name\": \"Academic Term\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Year\",\n \"name\": \"Academic Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Education Settings\",\n \"name\": \"Education Settings\",\n \"type\": \"doctype\"\n }\n]"
+ "label": "Masters",
+ "links": "[\n {\n \"label\": \"Program\",\n \"name\": \"Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Topic\",\n \"name\": \"Topic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@@ -22,33 +17,18 @@
},
{
"hidden": 0,
- "label": "Attendance",
- "links": "[\n {\n \"label\": \"Student Attendance\",\n \"name\": \"Student Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Leave Application\",\n \"name\": \"Student Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Absent Student Report\",\n \"name\": \"Absent Student Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Batch-Wise Attendance\",\n \"name\": \"Student Batch-Wise Attendance\",\n \"type\": \"report\"\n }\n]"
+ "label": "Settings",
+ "links": "[\n {\n \"label\": \"Education Settings\",\n \"name\": \"Education Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Category\",\n \"name\": \"Student Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Batch Name\",\n \"name\": \"Student Batch Name\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Grading Scale\",\n \"name\": \"Grading Scale\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Term\",\n \"name\": \"Academic Term\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Academic Year\",\n \"name\": \"Academic Year\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
"label": "Admission",
- "links": "[\n {\n \"label\": \"Student Applicant\",\n \"name\": \"Student Applicant\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Admission\",\n \"name\": \"Student Admission\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment\",\n \"name\": \"Program Enrollment\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"label\": \"Student Applicant\",\n \"name\": \"Student Applicant\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Admission\",\n \"name\": \"Student Admission\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment\",\n \"name\": \"Program Enrollment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Enrollment\",\n \"name\": \"Course Enrollment\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
- "label": "Assessment",
- "links": "[\n {\n \"label\": \"Assessment Plan\",\n \"name\": \"Assessment Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Group\",\n \"link\": \"Tree/Assessment Group\",\n \"name\": \"Assessment Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result\",\n \"name\": \"Assessment Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Criteria\",\n \"name\": \"Assessment Criteria\",\n \"type\": \"doctype\"\n }\n]"
- },
- {
- "hidden": 0,
- "label": "Student",
- "links": "[\n {\n \"label\": \"Student\",\n \"name\": \"Student\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Guardian\",\n \"name\": \"Guardian\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Log\",\n \"name\": \"Student Log\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group\",\n \"name\": \"Student Group\",\n \"type\": \"doctype\"\n }\n]"
- },
- {
- "hidden": 0,
- "label": "Masters",
- "links": "[\n {\n \"label\": \"Program\",\n \"name\": \"Program\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course\",\n \"name\": \"Course\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Topic\",\n \"name\": \"Topic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Instructor\",\n \"name\": \"Instructor\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Room\",\n \"name\": \"Room\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]"
- },
- {
- "hidden": 0,
- "label": "LMS Activity",
- "links": "[\n {\n \"label\": \"Course Enrollment\",\n \"name\": \"Course Enrollment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Activity\",\n \"name\": \"Course Activity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz Activity\",\n \"name\": \"Quiz Activity\",\n \"type\": \"doctype\"\n }\n]"
+ "label": "Fees",
+ "links": "[\n {\n \"label\": \"Fee Structure\",\n \"name\": \"Fee Structure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Category\",\n \"name\": \"Fee Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Schedule\",\n \"name\": \"Fee Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fees\",\n \"name\": \"Fees\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Student Fee Collection Report\",\n \"name\": \"Student Fee Collection\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Program wise Fee Collection Report\",\n \"name\": \"Program wise Fee Collection\",\n \"type\": \"report\"\n }\n]"
},
{
"hidden": 0,
@@ -57,8 +37,18 @@
},
{
"hidden": 0,
- "label": "Fees",
- "links": "[\n {\n \"label\": \"Fees\",\n \"name\": \"Fees\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Schedule\",\n \"name\": \"Fee Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Structure\",\n \"name\": \"Fee Structure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Fee Category\",\n \"name\": \"Fee Category\",\n \"type\": \"doctype\"\n }\n]"
+ "label": "Attendance",
+ "links": "[\n {\n \"label\": \"Student Attendance\",\n \"name\": \"Student Attendance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Leave Application\",\n \"name\": \"Student Leave Application\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Monthly Attendance Sheet\",\n \"name\": \"Student Monthly Attendance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Absent Student Report\",\n \"name\": \"Absent Student Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Batch-Wise Attendance\",\n \"name\": \"Student Batch-Wise Attendance\",\n \"type\": \"report\"\n }\n]"
+ },
+ {
+ "hidden": 0,
+ "label": "LMS Activity",
+ "links": "[\n {\n \"label\": \"Course Enrollment\",\n \"name\": \"Course Enrollment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Activity\",\n \"name\": \"Course Activity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Quiz Activity\",\n \"name\": \"Quiz Activity\",\n \"type\": \"doctype\"\n }\n]"
+ },
+ {
+ "hidden": 0,
+ "label": "Assessment",
+ "links": "[\n {\n \"label\": \"Assessment Plan\",\n \"name\": \"Assessment Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Group\",\n \"link\": \"Tree/Assessment Group\",\n \"name\": \"Assessment Group\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result\",\n \"name\": \"Assessment Result\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Criteria\",\n \"name\": \"Assessment Criteria\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@@ -67,28 +57,98 @@
},
{
"hidden": 0,
- "label": "Reports",
- "links": "[\n {\n \"dependencies\": [\n \"Fees\"\n ],\n \"doctype\": \"Fees\",\n \"is_query_report\": true,\n \"label\": \"Student Fee Collection\",\n \"name\": \"Student Fee Collection\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Monthly Attendance Sheet\",\n \"name\": \"Student Monthly Attendance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Absent Student Report\",\n \"name\": \"Absent Student Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Program Enrollment\"\n ],\n \"doctype\": \"Program Enrollment\",\n \"is_query_report\": true,\n \"label\": \"Student and Guardian Contact Details\",\n \"name\": \"Student and Guardian Contact Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Student Attendance\"\n ],\n \"doctype\": \"Student Attendance\",\n \"is_query_report\": true,\n \"label\": \"Student Batch-Wise Attendance\",\n \"name\": \"Student Batch-Wise Attendance\",\n \"type\": \"report\"\n }\n]"
+ "label": "Tools",
+ "links": "[\n {\n \"label\": \"Student Attendance Tool\",\n \"name\": \"Student Attendance Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Assessment Result Tool\",\n \"name\": \"Assessment Result Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Student Group Creation Tool\",\n \"name\": \"Student Group Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Program Enrollment Tool\",\n \"name\": \"Program Enrollment Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Course Scheduling Tool\",\n \"name\": \"Course Scheduling Tool\",\n \"type\": \"doctype\"\n }\n]"
+ },
+ {
+ "hidden": 0,
+ "label": "Other Reports",
+ "links": "[\n {\n \"dependencies\": [\n \"Program Enrollment\"\n ],\n \"doctype\": \"Program Enrollment\",\n \"is_query_report\": true,\n \"label\": \"Student and Guardian Contact Details\",\n \"name\": \"Student and Guardian Contact Details\",\n \"type\": \"report\"\n }\n]"
}
],
"category": "Domains",
- "charts": [],
+ "charts": [
+ {
+ "chart_name": "Program Enrollments",
+ "label": "Program Enrollments"
+ }
+ ],
"creation": "2020-03-02 17:22:57.066401",
"developer_mode_only": 0,
"disable_user_customization": 0,
"docstatus": 0,
"doctype": "Desk Page",
"extends_another_page": 0,
+ "hide_custom": 0,
"idx": 0,
"is_standard": 1,
"label": "Education",
- "modified": "2020-05-22 01:09:13.058482",
+ "modified": "2020-07-27 19:35:18.832694",
"modified_by": "Administrator",
"module": "Education",
"name": "Education",
+ "onboarding": "Education",
"owner": "Administrator",
"pin_to_bottom": 0,
"pin_to_top": 0,
"restrict_to_domain": "Education",
- "shortcuts": []
+ "shortcuts": [
+ {
+ "color": "#cef6d1",
+ "format": "{} Active",
+ "label": "Student",
+ "link_to": "Student",
+ "stats_filter": "{\n \"enabled\": 1\n}",
+ "type": "DocType"
+ },
+ {
+ "color": "#cef6d1",
+ "format": "{} Active",
+ "label": "Instructor",
+ "link_to": "Instructor",
+ "stats_filter": "{\n \"status\": \"Active\"\n}",
+ "type": "DocType"
+ },
+ {
+ "color": "",
+ "format": "",
+ "label": "Program",
+ "link_to": "Program",
+ "stats_filter": "",
+ "type": "DocType"
+ },
+ {
+ "label": "Course",
+ "link_to": "Course",
+ "type": "DocType"
+ },
+ {
+ "color": "#ffe8cd",
+ "format": "{} Unpaid",
+ "label": "Fees",
+ "link_to": "Fees",
+ "stats_filter": "{\n \"outstanding_amount\": [\"!=\", 0.0]\n}",
+ "type": "DocType"
+ },
+ {
+ "label": "Student Monthly Attendance Sheet",
+ "link_to": "Student Monthly Attendance Sheet",
+ "type": "Report"
+ },
+ {
+ "label": "Course Scheduling Tool",
+ "link_to": "Course Scheduling Tool",
+ "type": "DocType"
+ },
+ {
+ "label": "Student Attendance Tool",
+ "link_to": "Student Attendance Tool",
+ "type": "DocType"
+ },
+ {
+ "label": "Dashboard",
+ "link_to": "Education",
+ "type": "Dashboard"
+ }
+ ]
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js
index 12fdd91..63d1aee 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.js
+++ b/erpnext/education/doctype/assessment_result/assessment_result.js
@@ -6,10 +6,11 @@
if (!frm.doc.__islocal) {
frm.trigger('setup_chart');
}
+ frm.set_df_property('details', 'read_only', 1);
},
onload: function(frm) {
- frm.set_query('assessment_plan', function(){
+ frm.set_query('assessment_plan', function() {
return {
filters: {
docstatus: 1
@@ -27,14 +28,14 @@
},
callback: function(r) {
if (r.message) {
- frm.doc.details = [];
+ frappe.model.clear_table(frm.doc, 'details');
$.each(r.message, function(i, d) {
- var row = frappe.model.add_child(frm.doc, 'Assessment Result Detail', 'details');
+ var row = frm.add_child('details');
row.assessment_criteria = d.assessment_criteria;
row.maximum_score = d.maximum_score;
});
+ frm.refresh_field('details');
}
- refresh_field('details');
}
});
}
@@ -80,7 +81,7 @@
score: function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
- if(!d.maximum_score || !frm.doc.grading_scale) {
+ if (!d.maximum_score || !frm.doc.grading_scale) {
d.score = '';
frappe.throw(__('Please fill in all the details to generate Assessment Result.'));
}
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.json b/erpnext/education/doctype/assessment_result/assessment_result.json
index 212d47c..7a893aa 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.json
+++ b/erpnext/education/doctype/assessment_result/assessment_result.json
@@ -1,724 +1,182 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
+ "actions": [],
"allow_import": 1,
- "allow_rename": 0,
"autoname": "EDU-RES-.YYYY.-.#####",
- "beta": 0,
"creation": "2015-11-13 17:18:06.468332",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "assessment_plan",
+ "program",
+ "course",
+ "academic_year",
+ "academic_term",
+ "column_break_3",
+ "student",
+ "student_name",
+ "student_group",
+ "assessment_group",
+ "grading_scale",
+ "section_break_5",
+ "details",
+ "section_break_8",
+ "maximum_score",
+ "column_break_11",
+ "total_score",
+ "grade",
+ "section_break_13",
+ "comment",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "assessment_plan",
"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": "Assessment Plan",
- "length": 0,
- "no_copy": 0,
"options": "Assessment Plan",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.program",
"fieldname": "program",
"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": "Program",
- "length": 0,
- "no_copy": 0,
- "options": "Program",
- "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
+ "options": "Program"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.course",
"fieldname": "course",
"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": "Course",
- "length": 0,
- "no_copy": 0,
- "options": "Course",
- "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
+ "options": "Course"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.academic_year",
"fieldname": "academic_year",
"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": "Academic Year",
- "length": 0,
- "no_copy": 0,
- "options": "Academic Year",
- "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
+ "options": "Academic Year"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.academic_term",
"fieldname": "academic_term",
"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": "Academic Term",
- "length": 0,
- "no_copy": 0,
- "options": "Academic Term",
- "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
+ "options": "Academic Term"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "student",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Student",
- "length": 0,
- "no_copy": 0,
"options": "Student",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "student.title",
"fieldname": "student_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Student Name",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.student_group",
"fieldname": "student_group",
"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": "Student Group",
- "length": 0,
- "no_copy": 0,
- "options": "Student Group",
- "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
+ "options": "Student Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.assessment_group",
"fieldname": "assessment_group",
"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 Group",
- "length": 0,
- "no_copy": 0,
- "options": "Assessment Group",
- "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
+ "options": "Assessment Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.grading_scale",
"fieldname": "grading_scale",
"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": "Grading Scale",
- "length": 0,
- "no_copy": 0,
"options": "Grading Scale",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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,
- "label": "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,
- "translatable": 0,
- "unique": 0
+ "label": "Result"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
"fieldname": "details",
"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": "Details",
- "length": 0,
- "no_copy": 0,
"options": "Assessment Result Detail",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_8",
- "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
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.maximum_assessment_score",
"fieldname": "maximum_score",
"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": "Maximum Score",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "assessment_plan.maximum_assessment_score",
"fieldname": "column_break_11",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "total_score",
"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": "Total Score",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "grade",
"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": "Grade",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_13",
"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": "Summary",
- "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
+ "label": "Summary"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "comment",
"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": "Comment",
- "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
+ "label": "Comment"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "amended_from",
"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": "Amended From",
- "length": 0,
"no_copy": 1,
"options": "Assessment Result",
- "permlevel": 0,
"print_hide": 1,
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
"is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-30 02:10:36.813413",
+ "links": [],
+ "modified": "2020-08-03 11:47:54.119486",
"modified_by": "Administrator",
"module": "Education",
"name": "Assessment Result",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
@@ -728,28 +186,18 @@
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
- "set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "title_field": "student_name",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "title_field": "student_name"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.json b/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.json
index 85d943b..450f41c 100644
--- a/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.json
+++ b/erpnext/education/doctype/assessment_result_detail/assessment_result_detail.json
@@ -1,194 +1,66 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 0,
- "creation": "2016-12-14 17:44:35.583123",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2016-12-14 17:44:35.583123",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_criteria",
+ "maximum_score",
+ "column_break_2",
+ "score",
+ "grade"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 4,
- "fieldname": "assessment_criteria",
- "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": "Assessment Criteria",
- "length": 0,
- "no_copy": 0,
- "options": "Assessment Criteria",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "columns": 4,
+ "fieldname": "assessment_criteria",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Assessment Criteria",
+ "options": "Assessment Criteria",
+ "read_only": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "maximum_score",
- "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": "Maximum Score",
- "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
- },
+ "columns": 2,
+ "fieldname": "maximum_score",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Maximum Score",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "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,
- "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,
- "unique": 0
- },
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "score",
- "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": "Score",
- "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
- },
+ "columns": 2,
+ "fieldname": "score",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Score",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "grade",
- "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": "Grade",
- "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
+ "columns": 2,
+ "fieldname": "grade",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Grade",
+ "read_only": 1
}
- ],
- "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-11-10 19:11:14.362410",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Assessment Result Detail",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Education",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-31 13:27:17.699022",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Assessment Result Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Education",
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/fees/fees.json b/erpnext/education/doctype/fees/fees.json
index 99f9f4f..0fb7672 100644
--- a/erpnext/education/doctype/fees/fees.json
+++ b/erpnext/education/doctype/fees/fees.json
@@ -160,7 +160,8 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Program",
- "options": "Program"
+ "options": "Program",
+ "reqd": 1
},
{
"fieldname": "student_batch",
@@ -339,7 +340,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-07-18 05:00:00.621010",
+ "modified": "2020-08-05 14:05:47.728409",
"modified_by": "Administrator",
"module": "Education",
"name": "Fees",
diff --git a/erpnext/education/doctype/instructor/instructor.json b/erpnext/education/doctype/instructor/instructor.json
index 5367c0e..a417391 100644
--- a/erpnext/education/doctype/instructor/instructor.json
+++ b/erpnext/education/doctype/instructor/instructor.json
@@ -1,348 +1,125 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2015-11-04 15:56:30.004034",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Other",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2015-11-04 15:56:30.004034",
+ "doctype": "DocType",
+ "document_type": "Other",
+ "engine": "InnoDB",
+ "field_order": [
+ "instructor_name",
+ "employee",
+ "gender",
+ "column_break_5",
+ "status",
+ "naming_series",
+ "department",
+ "image",
+ "log_details",
+ "instructor_log"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "instructor_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Instructor 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "instructor_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Instructor Name",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "employee",
- "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": "Employee",
- "length": 0,
- "no_copy": 0,
- "options": "Employee",
- "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
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Employee",
+ "options": "Employee"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "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": "Naming Series",
- "length": 0,
- "no_copy": 0,
- "options": "EDU-INS-.YYYY.-",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "options": "EDU-INS-.YYYY.-",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.department",
- "fieldname": "department",
- "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": 1,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "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
- },
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Department",
+ "options": "Department"
+ },
{
- "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": 1,
- "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
- },
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "log_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": "Instructor Log",
- "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
- },
+ "fieldname": "log_details",
+ "fieldtype": "Section Break",
+ "label": "Instructor Log"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "instructor_log",
- "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": "Instructor Log",
- "length": 0,
- "no_copy": 0,
- "options": "Instructor Log",
- "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
+ "fieldname": "instructor_log",
+ "fieldtype": "Table",
+ "label": "Instructor Log",
+ "options": "Instructor Log"
+ },
+ {
+ "default": "Active",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Status",
+ "options": "Active\nLeft"
+ },
+ {
+ "fetch_from": "employee.gender",
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only_depends_on": "employee"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_field": "image",
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-01-30 11:28:17.571207",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Instructor",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "image_field": "image",
+ "links": [],
+ "modified": "2020-07-23 18:33:57.904398",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Instructor",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Instructor"
+ },
{
- "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": "Education Manager",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Education Manager",
+ "set_user_permissions": 1,
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Education",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "instructor_name",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Education",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "instructor_name"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 7536172..3e27670 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -97,6 +97,7 @@
return quiz_progress
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
if filters.get('program'):
return frappe.db.sql("""select course, course_name from `tabProgram Course`
@@ -115,6 +116,7 @@
})
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_students(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("academic_term"):
filters["academic_term"] = frappe.defaults.get_defaults().academic_term
diff --git a/erpnext/education/doctype/student/student.json b/erpnext/education/doctype/student/student.json
index bee915e..ac65c0c 100644
--- a/erpnext/education/doctype/student/student.json
+++ b/erpnext/education/doctype/student/student.json
@@ -1,1353 +1,305 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2015-09-07 13:00:55.938280",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "naming_series:",
+ "creation": "2015-09-07 13:00:55.938280",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "section_break_1",
+ "enabled",
+ "section_break_3",
+ "first_name",
+ "middle_name",
+ "last_name",
+ "user",
+ "column_break_4",
+ "naming_series",
+ "student_email_id",
+ "student_mobile_number",
+ "joining_date",
+ "image",
+ "section_break_7",
+ "date_of_birth",
+ "blood_group",
+ "column_break_3",
+ "gender",
+ "nationality",
+ "student_applicant",
+ "section_break_22",
+ "address_line_1",
+ "address_line_2",
+ "pincode",
+ "column_break_20",
+ "city",
+ "state",
+ "section_break_18",
+ "guardians",
+ "section_break_20",
+ "siblings",
+ "exit",
+ "date_of_leaving",
+ "leaving_certificate_number",
+ "column_break_31",
+ "reason_for_leaving",
+ "title"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_1",
- "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
- },
+ "fieldname": "section_break_1",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "enabled",
- "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": "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
- },
+ "default": "1",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_3",
- "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
- },
+ "fieldname": "section_break_3",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "first_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "First 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "first_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "First Name",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "middle_name",
- "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": "Middle 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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "middle_name",
+ "fieldtype": "Data",
+ "label": "Middle Name"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "last_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Last 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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "last_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Last Name"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 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": 0,
- "in_standard_filter": 0,
- "label": "User ID",
- "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
- },
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "label": "User ID",
+ "options": "User"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_4",
- "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
- },
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
- "fieldname": "naming_series",
- "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": "Naming Series",
- "length": 0,
- "no_copy": 1,
- "options": "EDU-STU-.YYYY.-",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "no_copy": 1,
+ "options": "EDU-STU-.YYYY.-",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "student_email_id",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Student Email 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "student_email_id",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Student Email Address",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "student_mobile_number",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Student Mobile Number",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "student_mobile_number",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Student Mobile Number"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fetch_if_empty": 0,
- "fieldname": "joining_date",
- "fieldtype": "Date",
- "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": "Joining Date",
- "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
- },
+ "default": "Today",
+ "fieldname": "joining_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Joining Date"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "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,
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image",
"width": "10"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "collapsible_depends_on": "",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_7",
- "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": "Personal 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
- },
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "label": "Personal Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "date_of_birth",
- "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": "Date of Birth",
- "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
- },
+ "fieldname": "date_of_birth",
+ "fieldtype": "Date",
+ "label": "Date of Birth"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "blood_group",
- "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": "Blood Group",
- "length": 0,
- "no_copy": 0,
- "options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-",
- "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
- },
+ "fieldname": "blood_group",
+ "fieldtype": "Select",
+ "label": "Blood Group",
+ "options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "gender",
- "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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "\nMale\nFemale\nOther",
- "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
- },
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "nationality",
- "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": "Nationality",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "nationality",
+ "fieldtype": "Data",
+ "label": "Nationality"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "student_applicant",
- "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": "Student Applicant",
- "length": 0,
- "no_copy": 0,
- "options": "Student Applicant",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "student_applicant",
+ "fieldtype": "Link",
+ "label": "Student Applicant",
+ "options": "Student Applicant",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_22",
- "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": "Home 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
- },
+ "fieldname": "section_break_22",
+ "fieldtype": "Section Break",
+ "label": "Home Address"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "address_line_1",
- "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": "Address Line 1",
- "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
- },
+ "fieldname": "address_line_1",
+ "fieldtype": "Data",
+ "label": "Address Line 1"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "address_line_2",
- "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": "Address Line 2",
- "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
- },
+ "fieldname": "address_line_2",
+ "fieldtype": "Data",
+ "label": "Address Line 2"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "pincode",
- "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": "Pincode",
- "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
- },
+ "fieldname": "pincode",
+ "fieldtype": "Data",
+ "label": "Pincode"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_20",
- "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
- },
+ "fieldname": "column_break_20",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "city",
- "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": "City",
- "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
- },
+ "fieldname": "city",
+ "fieldtype": "Data",
+ "label": "City"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "state",
- "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": "State",
- "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
- },
+ "fieldname": "state",
+ "fieldtype": "Data",
+ "label": "State"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_18",
- "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": "Guardian 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
- },
+ "fieldname": "section_break_18",
+ "fieldtype": "Section Break",
+ "label": "Guardian Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "guardians",
- "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": "Guardians",
- "length": 0,
- "no_copy": 0,
- "options": "Student Guardian",
- "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
- },
+ "fieldname": "guardians",
+ "fieldtype": "Table",
+ "label": "Guardians",
+ "options": "Student Guardian"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_20",
- "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": "Sibling Details",
- "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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "section_break_20",
+ "fieldtype": "Section Break",
+ "label": "Sibling Details",
+ "options": "Country"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "siblings",
- "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": "Siblings",
- "length": 0,
- "no_copy": 0,
- "options": "Student Sibling",
- "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
- },
+ "fieldname": "siblings",
+ "fieldtype": "Table",
+ "label": "Siblings",
+ "options": "Student Sibling"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "exit",
- "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": "Exit",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "exit",
+ "fieldtype": "Section Break",
+ "label": "Exit"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "date_of_leaving",
- "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": "Date of Leaving",
- "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
- },
+ "fieldname": "date_of_leaving",
+ "fieldtype": "Date",
+ "label": "Date of Leaving"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "leaving_certificate_number",
- "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": "Leaving Certificate Number",
- "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
- },
+ "fieldname": "leaving_certificate_number",
+ "fieldtype": "Data",
+ "label": "Leaving Certificate Number"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_31",
- "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
- },
+ "fieldname": "column_break_31",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "reason_for_leaving",
- "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": "Reason For Leaving",
- "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
- },
+ "fieldname": "reason_for_leaving",
+ "fieldtype": "Text",
+ "label": "Reason For Leaving"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Title",
- "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
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Title"
}
- ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_field": "image",
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-04-10 17:46:26.893020",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Student",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "image_field": "image",
+ "links": [],
+ "modified": "2020-07-23 18:14:06.366442",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "read": 1,
+ "role": "Instructor"
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "import": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Student",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Student",
+ "share": 1
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "LMS User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "LMS User",
+ "share": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "restrict_to_domain": "Education",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "title",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Education",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "title"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py
index 8b61c89..0260b80 100644
--- a/erpnext/education/doctype/student_group/student_group.py
+++ b/erpnext/education/doctype/student_group/student_group.py
@@ -108,6 +108,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def fetch_students(doctype, txt, searchfield, start, page_len, filters):
if filters.get("group_based_on") != "Activity":
enrolled_students = get_program_enrollment(filters.get('academic_year'), filters.get('academic_term'),
diff --git a/erpnext/education/education_dashboard/education/education.json b/erpnext/education/education_dashboard/education/education.json
new file mode 100644
index 0000000..41d3375
--- /dev/null
+++ b/erpnext/education/education_dashboard/education/education.json
@@ -0,0 +1,62 @@
+{
+ "cards": [
+ {
+ "card": "Total Students"
+ },
+ {
+ "card": "Total Instructors"
+ },
+ {
+ "card": "Program Enrollments"
+ },
+ {
+ "card": "Student Applicants to Review"
+ }
+ ],
+ "charts": [
+ {
+ "chart": "Program Enrollments",
+ "width": "Full"
+ },
+ {
+ "chart": "Program wise Enrollment",
+ "width": "Half"
+ },
+ {
+ "chart": "Course wise Enrollment",
+ "width": "Half"
+ },
+ {
+ "chart": "Course wise Student Count",
+ "width": "Half"
+ },
+ {
+ "chart": "Student Category wise Program Enrollments",
+ "width": "Half"
+ },
+ {
+ "chart": "Student Gender Diversity Ratio",
+ "width": "Half"
+ },
+ {
+ "chart": "Instructor Gender Diversity Ratio",
+ "width": "Half"
+ },
+ {
+ "chart": "Program wise Fee Collection",
+ "width": "Full"
+ }
+ ],
+ "creation": "2020-07-22 18:51:02.195762",
+ "dashboard_name": "Education",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-08-05 16:22:17.428101",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Education",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/education/module_onboarding/education/education.json b/erpnext/education/module_onboarding/education/education.json
new file mode 100644
index 0000000..e5f0fec
--- /dev/null
+++ b/erpnext/education/module_onboarding/education/education.json
@@ -0,0 +1,50 @@
+{
+ "allow_roles": [
+ {
+ "role": "Education Manager"
+ }
+ ],
+ "creation": "2020-07-27 19:02:49.561391",
+ "docstatus": 0,
+ "doctype": "Module Onboarding",
+ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/education",
+ "idx": 0,
+ "is_complete": 0,
+ "modified": "2020-07-27 21:10:46.722961",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Education",
+ "owner": "Administrator",
+ "steps": [
+ {
+ "step": "Create a Student"
+ },
+ {
+ "step": "Create an Instructor"
+ },
+ {
+ "step": "Introduction to Program and Courses"
+ },
+ {
+ "step": "Create a Topic"
+ },
+ {
+ "step": "Create a Course"
+ },
+ {
+ "step": "Create a Program"
+ },
+ {
+ "step": "Enroll a Student in a Program"
+ },
+ {
+ "step": "Introduction to Student Group"
+ },
+ {
+ "step": "Introduction to Student Attendance"
+ }
+ ],
+ "subtitle": "Students, Instructors, Programs and more.",
+ "success_message": "The Education Module is all set up!",
+ "title": "Let's Set Up the Education Module."
+}
diff --git a/erpnext/education/number_card/program_enrollments/program_enrollments.json b/erpnext/education/number_card/program_enrollments/program_enrollments.json
new file mode 100644
index 0000000..5847679
--- /dev/null
+++ b/erpnext/education/number_card/program_enrollments/program_enrollments.json
@@ -0,0 +1,23 @@
+{
+ "aggregate_function_based_on": "",
+ "creation": "2020-07-27 18:26:27.005186",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Program Enrollment",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Program Enrollment\",\"docstatus\",\"=\",\"1\",false],[\"Program Enrollment\",\"enrollment_date\",\"Timespan\",\"this year\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Program Enrollments",
+ "modified": "2020-07-27 18:26:32.512624",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program Enrollments",
+ "owner": "Administrator",
+ "report_function": "Sum",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Yearly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/education/number_card/student_applicants_to_review/student_applicants_to_review.json b/erpnext/education/number_card/student_applicants_to_review/student_applicants_to_review.json
new file mode 100644
index 0000000..258667a
--- /dev/null
+++ b/erpnext/education/number_card/student_applicants_to_review/student_applicants_to_review.json
@@ -0,0 +1,23 @@
+{
+ "aggregate_function_based_on": "",
+ "creation": "2020-07-27 18:42:33.366862",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Student Applicant",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Student Applicant\",\"application_status\",\"=\",\"Applied\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Student Applicants to Review",
+ "modified": "2020-07-27 18:42:42.739710",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Applicants to Review",
+ "owner": "Administrator",
+ "report_function": "Sum",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/education/number_card/total_instructors/total_instructors.json b/erpnext/education/number_card/total_instructors/total_instructors.json
new file mode 100644
index 0000000..b8d3cc0
--- /dev/null
+++ b/erpnext/education/number_card/total_instructors/total_instructors.json
@@ -0,0 +1,23 @@
+{
+ "aggregate_function_based_on": "",
+ "creation": "2020-07-23 14:19:38.423190",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Instructor",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Instructor\",\"status\",\"=\",\"Active\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Instructors",
+ "modified": "2020-07-23 14:19:47.623306",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Total Instructors",
+ "owner": "Administrator",
+ "report_function": "Sum",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/education/number_card/total_students/total_students.json b/erpnext/education/number_card/total_students/total_students.json
new file mode 100644
index 0000000..109c3d8
--- /dev/null
+++ b/erpnext/education/number_card/total_students/total_students.json
@@ -0,0 +1,23 @@
+{
+ "aggregate_function_based_on": "",
+ "creation": "2020-07-23 14:18:07.732298",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Student",
+ "dynamic_filters_json": "[]",
+ "filters_json": "[[\"Student\",\"enabled\",\"=\",1,false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Students",
+ "modified": "2020-07-23 14:18:40.603947",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Total Students",
+ "owner": "Administrator",
+ "report_function": "Sum",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/create_a_course/create_a_course.json b/erpnext/education/onboarding_step/create_a_course/create_a_course.json
new file mode 100644
index 0000000..02eee14
--- /dev/null
+++ b/erpnext/education/onboarding_step/create_a_course/create_a_course.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:09:04.493932",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:09:04.493932",
+ "modified_by": "Administrator",
+ "name": "Create a Course",
+ "owner": "Administrator",
+ "reference_document": "Course",
+ "show_full_form": 1,
+ "title": "Create a Course",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/create_a_program/create_a_program.json b/erpnext/education/onboarding_step/create_a_program/create_a_program.json
new file mode 100644
index 0000000..6172630
--- /dev/null
+++ b/erpnext/education/onboarding_step/create_a_program/create_a_program.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:09:35.451945",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:09:35.451945",
+ "modified_by": "Administrator",
+ "name": "Create a Program",
+ "owner": "Administrator",
+ "reference_document": "Program",
+ "show_full_form": 1,
+ "title": "Create a Program",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/create_a_student/create_a_student.json b/erpnext/education/onboarding_step/create_a_student/create_a_student.json
new file mode 100644
index 0000000..07c3f73
--- /dev/null
+++ b/erpnext/education/onboarding_step/create_a_student/create_a_student.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:17:20.326837",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:49:47.724289",
+ "modified_by": "Administrator",
+ "name": "Create a Student",
+ "owner": "Administrator",
+ "reference_document": "Student",
+ "show_full_form": 1,
+ "title": "Create a Student",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/create_a_topic/create_a_topic.json b/erpnext/education/onboarding_step/create_a_topic/create_a_topic.json
new file mode 100644
index 0000000..96a5364
--- /dev/null
+++ b/erpnext/education/onboarding_step/create_a_topic/create_a_topic.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:08:40.754534",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:09:13.231995",
+ "modified_by": "Administrator",
+ "name": "Create a Topic",
+ "owner": "Administrator",
+ "reference_document": "Topic",
+ "show_full_form": 1,
+ "title": "Create a Topic",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/create_an_instructor/create_an_instructor.json b/erpnext/education/onboarding_step/create_an_instructor/create_an_instructor.json
new file mode 100644
index 0000000..419d6e0
--- /dev/null
+++ b/erpnext/education/onboarding_step/create_an_instructor/create_an_instructor.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:17:39.158037",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:49:47.723494",
+ "modified_by": "Administrator",
+ "name": "Create an Instructor",
+ "owner": "Administrator",
+ "reference_document": "Instructor",
+ "show_full_form": 1,
+ "title": "Create an Instructor",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/enroll_a_student_in_a_program/enroll_a_student_in_a_program.json b/erpnext/education/onboarding_step/enroll_a_student_in_a_program/enroll_a_student_in_a_program.json
new file mode 100644
index 0000000..61e48cd
--- /dev/null
+++ b/erpnext/education/onboarding_step/enroll_a_student_in_a_program/enroll_a_student_in_a_program.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-07-27 19:10:28.530226",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:10:28.530226",
+ "modified_by": "Administrator",
+ "name": "Enroll a Student in a Program",
+ "owner": "Administrator",
+ "reference_document": "Program Enrollment",
+ "show_full_form": 0,
+ "title": "Enroll a Student in a Program",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/introduction_to_program_and_courses/introduction_to_program_and_courses.json b/erpnext/education/onboarding_step/introduction_to_program_and_courses/introduction_to_program_and_courses.json
new file mode 100644
index 0000000..a9ddfc0
--- /dev/null
+++ b/erpnext/education/onboarding_step/introduction_to_program_and_courses/introduction_to_program_and_courses.json
@@ -0,0 +1,19 @@
+{
+ "action": "Watch Video",
+ "creation": "2020-07-27 19:05:12.663987",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 20:18:11.831789",
+ "modified_by": "Administrator",
+ "name": "Introduction to Program and Courses",
+ "owner": "Administrator",
+ "show_full_form": 0,
+ "title": "Introduction to Program and Courses",
+ "validate_action": 1,
+ "video_url": "https://www.youtube.com/watch?v=1ueE4seFTp8"
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/introduction_to_student_attendance/introduction_to_student_attendance.json b/erpnext/education/onboarding_step/introduction_to_student_attendance/introduction_to_student_attendance.json
new file mode 100644
index 0000000..3de9972
--- /dev/null
+++ b/erpnext/education/onboarding_step/introduction_to_student_attendance/introduction_to_student_attendance.json
@@ -0,0 +1,19 @@
+{
+ "action": "Watch Video",
+ "creation": "2020-07-27 19:14:57.176131",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:55:55.411032",
+ "modified_by": "Administrator",
+ "name": "Introduction to Student Attendance",
+ "owner": "Administrator",
+ "show_full_form": 0,
+ "title": "Introduction to Student Attendance",
+ "validate_action": 1,
+ "video_url": "https://youtu.be/j9pgkPuyiaI"
+}
\ No newline at end of file
diff --git a/erpnext/education/onboarding_step/introduction_to_student_group/introduction_to_student_group.json b/erpnext/education/onboarding_step/introduction_to_student_group/introduction_to_student_group.json
new file mode 100644
index 0000000..74bdcd1
--- /dev/null
+++ b/erpnext/education/onboarding_step/introduction_to_student_group/introduction_to_student_group.json
@@ -0,0 +1,20 @@
+{
+ "action": "Watch Video",
+ "creation": "2020-07-27 19:12:05.046465",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-07-27 19:42:47.286441",
+ "modified_by": "Administrator",
+ "name": "Introduction to Student Group",
+ "owner": "Administrator",
+ "reference_document": "Student Group",
+ "show_full_form": 0,
+ "title": "Introduction to Student Group",
+ "validate_action": 1,
+ "video_url": "https://youtu.be/5K_smeeE1Q4"
+}
\ No newline at end of file
diff --git a/erpnext/education/report/program_wise_fee_collection/__init__.py b/erpnext/education/report/program_wise_fee_collection/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/report/program_wise_fee_collection/__init__.py
diff --git a/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.js b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.js
new file mode 100644
index 0000000..72e8f12
--- /dev/null
+++ b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Program wise Fee Collection"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+ "reqd": 1
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today(),
+ "reqd": 1
+ }
+ ]
+};
diff --git a/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.json b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.json
new file mode 100644
index 0000000..ee5c0de
--- /dev/null
+++ b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.json
@@ -0,0 +1,32 @@
+{
+ "add_total_row": 1,
+ "creation": "2020-07-27 16:05:33.263539",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2020-08-05 14:14:12.410515",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program wise Fee Collection",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "query": "SELECT \n FeesCollected.program AS \"Program:Link/Program:200\",\n FeesCollected.paid_amount AS \"Fees Collected:Currency:150\",\n FeesCollected.outstanding_amount AS \"Outstanding Amount:Currency:150\",\n FeesCollected.grand_total \"Grand Total:Currency:150\"\nFROM (\n SELECT \n sum(grand_total) - sum(outstanding_amount) AS paid_amount, program,\n sum(outstanding_amount) AS outstanding_amount,\n sum(grand_total) AS grand_total\n FROM `tabFees`\n WHERE docstatus = 1\n GROUP BY program\n) AS FeesCollected\nORDER BY FeesCollected.paid_amount DESC",
+ "ref_doctype": "Fees",
+ "report_name": "Program wise Fee Collection",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Academics User"
+ },
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Accounts Manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py
new file mode 100644
index 0000000..c145359
--- /dev/null
+++ b/erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py
@@ -0,0 +1,124 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+def execute(filters=None):
+ if not filters:
+ filters = {}
+
+ columns = get_columns(filters)
+ data = get_data(filters)
+ chart = get_chart_data(data)
+
+ return columns, data, None, chart
+
+def get_columns(filters=None):
+ return [
+ {
+ 'label': _('Program'),
+ 'fieldname': 'program',
+ 'fieldtype': 'Link',
+ 'options': 'Program',
+ 'width': 300
+ },
+ {
+ 'label': _('Fees Collected'),
+ 'fieldname': 'fees_collected',
+ 'fieldtype': 'Currency',
+ 'width': 200
+ },
+ {
+ 'label': _('Outstanding Amount'),
+ 'fieldname': 'outstanding_amount',
+ 'fieldtype': 'Currency',
+ 'width': 200
+ },
+ {
+ 'label': _('Grand Total'),
+ 'fieldname': 'grand_total',
+ 'fieldtype': 'Currency',
+ 'width': 200
+ }
+ ]
+
+
+def get_data(filters=None):
+ data = []
+
+ conditions = get_filter_conditions(filters)
+
+ fee_details = frappe.db.sql(
+ """
+ SELECT
+ FeesCollected.program,
+ FeesCollected.paid_amount,
+ FeesCollected.outstanding_amount,
+ FeesCollected.grand_total
+ FROM (
+ SELECT
+ sum(grand_total) - sum(outstanding_amount) AS paid_amount, program,
+ sum(outstanding_amount) AS outstanding_amount,
+ sum(grand_total) AS grand_total
+ FROM `tabFees`
+ WHERE
+ docstatus = 1 and
+ program IS NOT NULL
+ %s
+ GROUP BY program
+ ) AS FeesCollected
+ ORDER BY FeesCollected.paid_amount DESC
+ """ % (conditions)
+ , as_dict=1)
+
+ for entry in fee_details:
+ data.append({
+ 'program': entry.program,
+ 'fees_collected': entry.paid_amount,
+ 'outstanding_amount': entry.outstanding_amount,
+ 'grand_total': entry.grand_total
+ })
+
+ return data
+
+def get_filter_conditions(filters):
+ conditions = ''
+
+ if filters.get('from_date') and filters.get('to_date'):
+ conditions += " and posting_date BETWEEN '%s' and '%s'" % (filters.get('from_date'), filters.get('to_date'))
+
+ return conditions
+
+
+def get_chart_data(data):
+ if not data:
+ return
+
+ labels = []
+ fees_collected = []
+ outstanding_amount = []
+
+ for entry in data:
+ labels.append(entry.get('program'))
+ fees_collected.append(entry.get('fees_collected'))
+ outstanding_amount.append(entry.get('outstanding_amount'))
+
+ return {
+ 'data': {
+ 'labels': labels,
+ 'datasets': [
+ {
+ 'name': _('Fees Collected'),
+ 'values': fees_collected
+ },
+ {
+ 'name': _('Outstanding Amt'),
+ 'values': outstanding_amount
+ }
+ ]
+ },
+ 'type': 'bar'
+ }
+
diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py
index 633692d..24fc3d4 100644
--- a/erpnext/erpnext_integrations/taxjar_integration.py
+++ b/erpnext/erpnext_integrations/taxjar_integration.py
@@ -1,8 +1,5 @@
import traceback
-import pycountry
-import taxjar
-
import frappe
from erpnext import get_default_company
from frappe import _
@@ -32,6 +29,7 @@
def create_transaction(doc, method):
+ import taxjar
"""Create an order transaction in TaxJar"""
if not TAXJAR_CREATE_TRANSACTIONS:
@@ -208,6 +206,7 @@
def get_iso_3166_2_state_code(address):
+ import pycountry
country_code = frappe.db.get_value("Country", address.get("country"), "code")
error_message = _("""{0} is not a valid state! Check for typos or enter the ISO code for your state.""").format(address.get("state"))
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
index 3dc7c1e..5da5a06 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
@@ -71,6 +71,7 @@
frappe.throw(_(msg))
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
fields = ['name', 'practitioner_name', 'mobile_phone']
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
index 69356ba..bc76970 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
@@ -222,6 +222,7 @@
inpatient_record.save(ignore_permissions = True)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_leave_from(doctype, txt, searchfield, start, page_len, filters):
docname = filters['docname']
diff --git a/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json b/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json
index bfcfa96..42a8309 100644
--- a/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json
+++ b/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json
@@ -7,14 +7,14 @@
"doctype": "Dashboard Chart",
"document_type": "Job Applicant",
"dynamic_filters_json": "",
- "filters_json": "[[\"Job Applicant\",\"creation\",\"Previous\",\"1 month\"]]",
+ "filters_json": "[[\"Job Applicant\",\"creation\",\"Timespan\",\"last month\",false]]",
"group_by_based_on": "status",
"group_by_type": "Count",
"idx": 0,
"is_public": 1,
"is_standard": 1,
- "last_synced_on": "2020-07-22 14:27:40.118498",
- "modified": "2020-07-22 14:33:00.404144",
+ "last_synced_on": "2020-07-28 16:19:12.109979",
+ "modified": "2020-07-28 16:19:45.279490",
"modified_by": "Administrator",
"module": "HR",
"name": "Job Application Status",
diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py
index d4c118f..afd54b8 100644
--- a/erpnext/hr/doctype/department_approver/department_approver.py
+++ b/erpnext/hr/doctype/department_approver/department_approver.py
@@ -11,6 +11,7 @@
pass
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_approvers(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("employee"):
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
index 4b9b928..42f7cdb 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
@@ -35,7 +35,15 @@
"fieldname":"employee",
"label": __("Employee"),
"fieldtype": "Link",
- "options": "Employee"
+ "options": "Employee",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ };
+ }
},
{
"fieldname":"company",
diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py
index 8672094..e961114 100644
--- a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py
+++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py
@@ -96,33 +96,35 @@
def get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map):
data = []
- for jo in sp_jo_map[sp]:
- row = {
- "staffing_plan" : sp,
- "job_opening" : jo["name"],
- }
- data.append(row)
- child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map)
- data += child_row
+ if sp in sp_jo_map.keys():
+ for jo in sp_jo_map[sp]:
+ row = {
+ "staffing_plan" : sp,
+ "job_opening" : jo["name"],
+ }
+ data.append(row)
+ child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map)
+ data += child_row
return data
def get_child_row(jo, jo_ja_map, ja_joff_map):
data = []
- for ja in jo_ja_map[jo]:
- row = {
- "indent":1,
- "job_applicant": ja.name,
- "applicant_name": ja.applicant_name,
- "application_status": ja.status,
- }
- if ja.name in ja_joff_map.keys():
- jo_detail =ja_joff_map[ja.name][0]
- row["job_offer"] = jo_detail.name
- row["job_offer_status"] = jo_detail.status
- row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y")
- row["designation"] = jo_detail.designation
+ if jo in jo_ja_map.keys():
+ for ja in jo_ja_map[jo]:
+ row = {
+ "indent":1,
+ "job_applicant": ja.name,
+ "applicant_name": ja.applicant_name,
+ "application_status": ja.status,
+ }
+ if ja.name in ja_joff_map.keys():
+ jo_detail =ja_joff_map[ja.name][0]
+ row["job_offer"] = jo_detail.name
+ row["job_offer_status"] = jo_detail.status
+ row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y")
+ row["designation"] = jo_detail.designation
- data.append(row)
+ data.append(row)
return data
def get_staffing_plan(filters):
@@ -177,7 +179,7 @@
def get_job_offer(ja_list):
ja_joff_map = {}
- offers = frappe.get_all("Job offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation'])
+ offers = frappe.get_all("Job Offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation'])
for offer in offers:
if offer.job_applicant not in ja_joff_map.keys():
diff --git a/erpnext/loan_management/desk_page/loan/loan.json b/erpnext/loan_management/desk_page/loan/loan.json
index 48193b0..3bdd1ce 100644
--- a/erpnext/loan_management/desk_page/loan/loan.json
+++ b/erpnext/loan_management/desk_page/loan/loan.json
@@ -3,7 +3,7 @@
{
"hidden": 0,
"label": "Loan",
- "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n { \"dependencies\": [\n \"Loan Type\"\n ],\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index 192beee..aa5e21b 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -20,8 +20,8 @@
"section_break_8",
"loan_type",
"loan_amount",
- "is_secured_loan",
"rate_of_interest",
+ "is_secured_loan",
"disbursement_date",
"disbursed_amount",
"column_break_11",
@@ -334,7 +334,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-07-02 20:46:40.128142",
+ "modified": "2020-08-01 12:36:11.255233",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index c65996e..23815d598 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -269,7 +269,7 @@
self.assertTrue(loan_security_shortfall)
self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
- self.assertEquals(loan_security_shortfall.security_value, 400000.00)
+ self.assertEquals(loan_security_shortfall.security_value, 800000.00)
self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index 6cf47bf..b56fce1 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -112,16 +112,19 @@
frappe.ui.form.on("Proposed Pledge", {
loan_security: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
- frappe.call({
- method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
- args: {
- loan_security: row.loan_security
- },
- callback: function(r) {
- frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
- frm.events.calculate_amounts(frm, cdt, cdn);
- }
- })
+
+ if (row.loan_security) {
+ frappe.call({
+ method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
+ args: {
+ loan_security: row.loan_security
+ },
+ callback: function(r) {
+ frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
+ frm.events.calculate_amounts(frm, cdt, cdn);
+ }
+ })
+ }
},
amount: function(frm, cdt, cdn) {
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index e6ceb55..b56fa80 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -19,8 +19,8 @@
if not self.posting_date:
self.posting_date = nowdate()
- if not self.interest_amount:
- frappe.throw(_("Interest Amount is mandatory"))
+ if not self.interest_amount and not self.payable_principal_amount:
+ frappe.throw(_("Interest Amount or Principal Amount is mandatory"))
def on_submit(self):
@@ -39,37 +39,38 @@
def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = []
- gle_map.append(
- self.get_gl_dict({
- "account": self.loan_account,
- "party_type": self.applicant_type,
- "party": self.applicant,
- "against": self.interest_income_account,
- "debit": self.interest_amount,
- "debit_in_account_currency": self.interest_amount,
- "against_voucher_type": "Loan",
- "against_voucher": self.loan,
- "remarks": _("Against Loan:") + self.loan,
- "cost_center": erpnext.get_default_cost_center(self.company),
- "posting_date": self.posting_date
- })
- )
+ if self.interest_amount:
+ gle_map.append(
+ self.get_gl_dict({
+ "account": self.loan_account,
+ "party_type": self.applicant_type,
+ "party": self.applicant,
+ "against": self.interest_income_account,
+ "debit": self.interest_amount,
+ "debit_in_account_currency": self.interest_amount,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.loan,
+ "remarks": _("Against Loan:") + self.loan,
+ "cost_center": erpnext.get_default_cost_center(self.company),
+ "posting_date": self.posting_date
+ })
+ )
- gle_map.append(
- self.get_gl_dict({
- "account": self.interest_income_account,
- "party_type": self.applicant_type,
- "party": self.applicant,
- "against": self.loan_account,
- "credit": self.interest_amount,
- "credit_in_account_currency": self.interest_amount,
- "against_voucher_type": "Loan",
- "against_voucher": self.loan,
- "remarks": _("Against Loan:") + self.loan,
- "cost_center": erpnext.get_default_cost_center(self.company),
- "posting_date": self.posting_date
- })
- )
+ gle_map.append(
+ self.get_gl_dict({
+ "account": self.interest_income_account,
+ "party_type": self.applicant_type,
+ "party": self.applicant,
+ "against": self.loan_account,
+ "credit": self.interest_amount,
+ "credit_in_account_currency": self.interest_amount,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.loan,
+ "remarks": _("Against Loan:") + self.loan,
+ "cost_center": erpnext.get_default_cost_center(self.company),
+ "posting_date": self.posting_date
+ })
+ )
if gle_map:
make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 789c129..5942455 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -173,7 +173,7 @@
{
"fieldname": "references_section",
"fieldtype": "Section Break",
- "label": "References"
+ "label": "Payment References"
},
{
"fieldname": "reference_number",
@@ -221,7 +221,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-04-16 18:14:45.166754",
+ "modified": "2020-05-16 09:40:15.581165",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Repayment",
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
index 82837b3..11c932f 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
@@ -22,16 +22,19 @@
frappe.ui.form.on("Pledge", {
loan_security: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
- frappe.call({
- method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
- args: {
- loan_security: row.loan_security
- },
- callback: function(r) {
- frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
- frm.events.calculate_amounts(frm, cdt, cdn);
- }
- });
+
+ if (row.loan_security) {
+ frappe.call({
+ method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
+ args: {
+ loan_security: row.loan_security
+ },
+ callback: function(r) {
+ frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
+ frm.events.calculate_amounts(frm, cdt, cdn);
+ }
+ });
+ }
},
qty: function(frm, cdt, cdn) {
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
index 961c05c..2bb6fd8 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
@@ -14,6 +14,7 @@
def validate(self):
self.set_pledge_amount()
self.validate_duplicate_securities()
+ self.validate_loan_security_type()
def on_submit(self):
if self.loan:
@@ -31,6 +32,27 @@
frappe.throw(_('Loan Security {0} added multiple times').format(frappe.bold(
security.loan_security)))
+ def validate_loan_security_type(self):
+ existing_pledge = ''
+
+ if self.loan:
+ existing_pledge = frappe.db.get_value('Loan Security Pledge', {'loan': self.loan}, ['name'])
+
+ if existing_pledge:
+ loan_security_type = frappe.db.get_value('Pledge', {'parent': existing_pledge}, ['loan_security_type'])
+ else:
+ loan_security_type = self.securities[0].loan_security_type
+
+ ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type",
+ fields=["name", "loan_to_value_ratio"], as_list=1))
+
+ ltv_ratio = ltv_ratio_map.get(loan_security_type)
+
+ for security in self.securities:
+ if ltv_ratio_map.get(security.loan_security_type) != ltv_ratio:
+ frappe.throw(_("Loan Securities with different LTV ratio cannot be pledged against one loan"))
+
+
def set_pledge_amount(self):
total_security_value = 0
maximum_loan_value = 0
diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
index ffd9673..02efe24 100644
--- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
@@ -7,6 +7,7 @@
from frappe.utils import get_datetime
from frappe.model.document import Document
from six import iteritems
+from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
class LoanSecurityShortfall(Document):
pass
@@ -50,31 +51,30 @@
"valid_upto": (">=", update_time)
}, as_list=1))
- ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type",
- fields=["name", "loan_to_value_ratio"], as_list=1))
-
- loans = frappe.db.sql(""" SELECT l.name, l.loan_amount, l.total_principal_paid, lp.loan_security, lp.haircut, lp.qty, lp.loan_security_type
- FROM `tabLoan` l, `tabPledge` lp , `tabLoan Security Pledge`p WHERE lp.parent = p.name and p.loan = l.name and l.docstatus = 1
- and l.is_secured_loan and l.status = 'Disbursed' and p.status = 'Pledged'""", as_dict=1)
+ loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'],
+ filters={'status': 'Disbursed', 'is_secured_loan': 1})
loan_security_map = {}
for loan in loans:
- loan_security_map.setdefault(loan.name, {
- "loan_amount": loan.loan_amount - loan.total_principal_paid,
- "security_value": 0.0
- })
+ outstanding_amount = loan.loan_amount - loan.total_principal_paid
+ pledged_securities = get_pledged_security_qty(loan.name)
+ ltv_ratio = ''
+ security_value = 0.0
- current_loan_security_amount = loan_security_price_map.get(loan.loan_security, 0) * loan.qty
- ltv_ratio = ltv_ratio_map.get(loan.loan_security_type)
+ for security, qty in pledged_securities.items():
+ if not ltv_ratio:
+ ltv_ratio = get_ltv_ratio(security)
+ security_value += loan_security_price_map.get(security) * qty
- loan_security_map[loan.name]['security_value'] += current_loan_security_amount - (current_loan_security_amount * loan.haircut/100)
+ current_ratio = (outstanding_amount/security_value) * 100
- for loan, value in iteritems(loan_security_map):
- if (value["loan_amount"]/value['security_value'] * 100) > ltv_ratio:
- create_loan_security_shortfall(loan, value, process_loan_security_shortfall)
+ if current_ratio > ltv_ratio:
+ shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
+ create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount,
+ process_loan_security_shortfall)
-def create_loan_security_shortfall(loan, value, process_loan_security_shortfall):
+def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, process_loan_security_shortfall):
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
@@ -85,9 +85,14 @@
ltv_shortfall.loan = loan
ltv_shortfall.shortfall_time = get_datetime()
- ltv_shortfall.loan_amount = value["loan_amount"]
- ltv_shortfall.security_value = value["security_value"]
- ltv_shortfall.shortfall_amount = value["loan_amount"] - value["security_value"]
+ ltv_shortfall.loan_amount = loan_amount
+ ltv_shortfall.security_value = security_value
+ ltv_shortfall.shortfall_amount = shortfall_amount
ltv_shortfall.process_loan_security_shortfall = process_loan_security_shortfall
ltv_shortfall.save()
+def get_ltv_ratio(loan_security):
+ loan_security_type = frappe.db.get_value('Loan Security', loan_security, 'loan_security_type')
+ ltv_ratio = frappe.db.get_value('Loan Security Type', loan_security_type, 'loan_to_value_ratio')
+ return ltv_ratio
+
diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
index f46b88c..871e825 100644
--- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
+++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
@@ -29,6 +29,7 @@
"unique": 1
},
{
+ "description": "Haircut percentage is the percentage difference between market value of the Loan Security and the value ascribed to that Loan Security when used as collateral for that loan.",
"fieldname": "haircut",
"fieldtype": "Percent",
"label": "Haircut %"
@@ -46,13 +47,14 @@
"fieldtype": "Column Break"
},
{
+ "description": "Loan To Value Ratio expresses the ratio of the loan amount to the value of the security pledged. A loan security shortfall will be triggered if this falls below the specified value for any loan ",
"fieldname": "loan_to_value_ratio",
"fieldtype": "Percent",
"label": "Loan To Value Ratio"
}
],
"links": [],
- "modified": "2020-04-28 14:06:49.046177",
+ "modified": "2020-05-16 09:38:45.988080",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Security Type",
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index 1dd3710..669490a 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -76,6 +76,7 @@
"reqd": 1
},
{
+ "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower",
"fieldname": "payment_account",
"fieldtype": "Link",
"label": "Payment Account",
@@ -83,6 +84,7 @@
"reqd": 1
},
{
+ "description": "This account is capital account which is used to allocate capital for loan disbursal account ",
"fieldname": "loan_account",
"fieldtype": "Link",
"label": "Loan Account",
@@ -94,6 +96,7 @@
"fieldtype": "Column Break"
},
{
+ "description": "This account will be used for booking loan interest accruals",
"fieldname": "interest_income_account",
"fieldtype": "Link",
"label": "Interest Income Account",
@@ -101,6 +104,7 @@
"reqd": 1
},
{
+ "description": "This account will be used for booking penalties levied due to delayed repayments",
"fieldname": "penalty_income_account",
"fieldtype": "Link",
"label": "Penalty Income Account",
@@ -109,6 +113,7 @@
},
{
"default": "0",
+ "description": "If this is not checked the loan by default will be considered as a Demand Loan",
"fieldname": "is_term_loan",
"fieldtype": "Check",
"label": "Is Term Loan"
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 8062342..c51f655 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -911,6 +911,7 @@
return out
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_query(doctype, txt, searchfield, start, page_len, filters):
meta = frappe.get_meta("Item", cached=True)
searchfields = meta.get_search_fields()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index f962a11..b7d968e 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -632,6 +632,7 @@
return bom
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_bom_operations(doctype, txt, searchfield, start, page_len, filters):
if txt:
filters['operation'] = ('like', '%%%s%%' % txt)
diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
index e3e440e..dc424b7 100644
--- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
+++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
@@ -30,7 +30,7 @@
"width": 180
}
])
-
+
columns.extend([
{
"label": _("Finished Good"),
@@ -73,7 +73,7 @@
])
return columns
-
+
def get_data(filters):
cond = "1=1"
@@ -95,6 +95,7 @@
return results
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_work_orders(doctype, txt, searchfield, start, page_len, filters):
cond = "1=1"
if filters.get('bom_no'):
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
index 5ac3923..ebc01c6 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
@@ -369,6 +369,3 @@
"fieldtype": "Float",
"width": 140
}])
-
-def document_query(doctype, txt, searchfield, start, page_len, filters):
- pass
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 3bd4169..49af0ba 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -679,7 +679,6 @@
erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
erpnext.patches.v12_0.rename_pos_closing_doctype
erpnext.patches.v13_0.replace_pos_payment_mode_table
-erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
erpnext.patches.v12_0.remove_duplicate_leave_ledger_entries #2020-05-22
erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
execute:frappe.reload_doc("HR", "doctype", "Employee Advance")
@@ -688,6 +687,7 @@
execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
+erpnext.patches.v13_0.update_old_loans
erpnext.patches.v12_0.set_serial_no_status #2020-05-21
erpnext.patches.v12_0.update_price_list_currency_in_bom
execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
diff --git a/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py b/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py
deleted file mode 100644
index ca8a13b..0000000
--- a/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # to retain the roles and permissions from Education Module
- # after moving doctype to core
- permissions = frappe.db.sql("""
- SELECT
- *
- FROM
- `tabDocPerm`
- WHERE
- parent='Video'
- """, as_dict=True)
-
- frappe.reload_doc('core', 'doctype', 'video')
- doc = frappe.get_doc('DocType', 'Video')
- doc.permissions = []
- for perm in permissions:
- doc.append('permissions', perm)
- doc.save()
diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py
new file mode 100644
index 0000000..7723942
--- /dev/null
+++ b/erpnext/patches/v13_0/update_old_loans.py
@@ -0,0 +1,88 @@
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import nowdate
+from erpnext.accounts.doctype.account.test_account import create_account
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
+from erpnext.loan_management.doctype.loan.loan import make_repayment_entry
+
+def execute():
+
+ # Create a penalty account for loan types
+
+ frappe.reload_doc('loan_management', 'doctype', 'loan_type')
+ frappe.reload_doc('loan_management', 'doctype', 'loan')
+ frappe.reload_doc('loan_management', 'doctype', 'repayment_schedule')
+ frappe.reload_doc('loan_management', 'doctype', 'process_loan_interest_accrual')
+ frappe.reload_doc('loan_management', 'doctype', 'loan_repayment')
+ frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail')
+ frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual')
+ frappe.reload_doc('accounts', 'doctype', 'gl_entry')
+
+ updated_loan_types = []
+
+ loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment',
+ 'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'])
+
+ for loan in loans:
+ # Update details in Loan Types and Loan
+ loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company')
+
+ group_income_account = frappe.get_value('Account', {'company': loan.company,
+ 'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')})
+
+ if not group_income_account:
+ group_income_account = frappe.get_value('Account', {'company': loan.company,
+ 'is_group': 1, 'root_type': 'Income'})
+
+ penalty_account = create_account(company=loan.company, account_type='Income Account',
+ account_name='Penalty Account', parent_account=group_income_account)
+
+ if not loan_type_company:
+ loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type)
+ loan_type_doc.is_term_loan = 1
+ loan_type_doc.company = loan.company
+ loan_type_doc.mode_of_payment = loan.mode_of_payment
+ loan_type_doc.payment_account = loan.payment_account
+ loan_type_doc.loan_account = loan.loan_account
+ loan_type_doc.interest_income_account = loan.interest_income_account
+ loan_type_doc.penalty_income_account = penalty_account
+ loan_type_doc.submit()
+ updated_loan_types.append(loan.loan_type)
+
+ if loan.loan_type in updated_loan_types:
+ if loan.status == 'Fully Disbursed':
+ status = 'Disbursed'
+ elif loan.status == 'Repaid/Closed':
+ status = 'Closed'
+ else:
+ status = loan.status
+
+ frappe.db.set_value('Loan', loan.name, {
+ 'is_term_loan': 1,
+ 'penalty_income_account': penalty_account,
+ 'status': status
+ })
+
+ process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type,
+ loan=loan.name)
+
+ payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date
+ FROM `tabJournal Entry` j, `tabJournal Entry Account` a
+ WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s
+ and account = %s
+ ''', (loan.name, loan.loan_account), as_dict=1)
+
+ for payment in payments:
+ repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant,
+ loan.loan_type, loan.company)
+
+ repayment_entry.amount_paid = payment.debit_in_account_currency
+ repayment_entry.posting_date = payment.posting_date
+ repayment_entry.save()
+ repayment_entry.submit()
+
+ jv = frappe.get_doc('Journal Entry', payment.name)
+ jv.flags.ignore_links = True
+ jv.cancel()
+
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index d7d00e6..ef844fb 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -223,6 +223,7 @@
return benefit_amount
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
if len(filters) < 2:
return {}
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index ad9b6d8..554484f 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -540,6 +540,7 @@
frappe.msgprint(_("Could not submit some Salary Slips"))
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
select name from `tabPayroll Entry`
diff --git a/erpnext/portal/doctype/products_settings/products_settings.py b/erpnext/portal/doctype/products_settings/products_settings.py
index b984aeb..ae7dc68 100644
--- a/erpnext/portal/doctype/products_settings/products_settings.py
+++ b/erpnext/portal/doctype/products_settings/products_settings.py
@@ -11,9 +11,9 @@
class ProductsSettings(Document):
def validate(self):
if self.home_page_is_products:
- frappe.db.set_value("Website Settings", "home_page", "products")
+ frappe.db.set_value("Website Settings", None, "home_page", "products")
elif frappe.db.get_single_value("Website Settings", "home_page") == 'products':
- frappe.db.set_value("Website Settings", "home_page", "home")
+ frappe.db.set_value("Website Settings", None, "home_page", "home")
self.validate_field_filters()
self.validate_attribute_filters()
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index f8af30a..9eef16b 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -239,7 +239,8 @@
if exact_match:
data = get_product_info_for_website(exact_match[0])
product_info = data.product_info
- product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
+ if product_info:
+ product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
if not data.cart_settings.show_price:
product_info = None
else:
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 6350f86..5bbd29c 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -239,6 +239,7 @@
}
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
conditions = []
return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index cf2fd26..fb84094 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -193,6 +193,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_project(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
return frappe.db.sql(""" select name from `tabProject`
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index 7fe22be..9e807f7 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -214,6 +214,7 @@
and sales_invoice is null""".format(cond), {'project': project, 'parent': parent}, as_dict=1)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_timesheet(doctype, txt, searchfield, start, page_len, filters):
if not filters: filters = {}
diff --git a/erpnext/projects/utils.py b/erpnext/projects/utils.py
index d0d88eb..c39f908 100644
--- a/erpnext/projects/utils.py
+++ b/erpnext/projects/utils.py
@@ -7,6 +7,7 @@
import frappe
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def query_task(doctype, txt, searchfield, start, page_len, filters):
from frappe.desk.reportview import build_match_conditions
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 2d306ba..787d557 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -234,9 +234,6 @@
self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \
flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2)
- for k, v in iteritems(account_map):
- txval -= self.report_dict.get(supply_type, {}).get(supply_category, {}).get(v, 0)
-
self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2)
def set_inter_state_supply(self, inter_state_supply):
@@ -256,7 +253,7 @@
def get_total_taxable_value(self, doctype, reverse_charge):
return frappe._dict(frappe.db.sql("""
- select gst_category, sum(base_grand_total) as total
+ select gst_category, sum(net_total) as total
from `tab{doctype}`
where docstatus = 1 and month(posting_date) = %s
and year(posting_date) = %s and reverse_charge = %s
@@ -309,26 +306,27 @@
inter_state_supply_tax_mapping.setdefault(d.name, {
'place_of_supply': d.place_of_supply,
'taxable_value': d.net_total,
+ 'gst_category': d.gst_category,
'camt': 0.0,
'samt': 0.0,
'iamt': 0.0,
'csamt': 0.0
})
- if d.account_head in [d.cgst_account for d in self.account_heads]:
+ if d.account_head in [a.cgst_account for a in self.account_heads]:
inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount
- if d.account_head in [d.sgst_account for d in self.account_heads]:
+ if d.account_head in [a.sgst_account for a in self.account_heads]:
inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount
- if d.account_head in [d.igst_account for d in self.account_heads]:
+ if d.account_head in [a.igst_account for a in self.account_heads]:
inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount
- if d.account_head in [d.cess_account for d in self.account_heads]:
+ if d.account_head in [a.cess_account for a in self.account_heads]:
inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount
for key, value in iteritems(inter_state_supply_tax_mapping):
- if d.place_of_supply:
+ if value.get('place_of_supply'):
osup_det = self.report_dict["sup_details"]["osup_det"]
osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2)
osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2)
@@ -336,15 +334,15 @@
osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2)
osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2)
- if state_number != d.place_of_supply.split("-")[0]:
- inter_state_supply_details.setdefault((d.gst_category, d.place_of_supply), {
+ if state_number != value.get('place_of_supply').split("-")[0]:
+ inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), {
"txval": 0.0,
- "pos": d.place_of_supply.split("-")[0],
+ "pos": value.get('place_of_supply').split("-")[0],
"iamt": 0.0
})
- inter_state_supply_details[(d.gst_category, d.place_of_supply)]['txval'] += value['taxable_value']
- inter_state_supply_details[(d.gst_category, d.place_of_supply)]['iamt'] += value['iamt']
+ inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['txval'] += value['taxable_value']
+ inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['iamt'] += value['iamt']
return inter_state_supply_details
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index 4d36cff..fbccc6b 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -10,6 +10,8 @@
frm.trigger('get_tax_template');
},
get_tax_template: function(frm) {
+ if (!frm.doc.company) return;
+
let party_details = {
'shipping_address': frm.doc.shipping_address || '',
'shipping_address_name': frm.doc.shipping_address_name || '',
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index e614acd..ca62488 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -340,6 +340,7 @@
return lp_details
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
from erpnext.controllers.queries import get_fields
fields = ["name", "customer_name", "customer_group", "territory"]
@@ -542,6 +543,7 @@
return address
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
customer = filters.get('customer')
return frappe.db.sql("""
diff --git a/erpnext/selling/doctype/lead_source/lead_source.json b/erpnext/selling/doctype/lead_source/lead_source.json
index 868f6d1..373e83a 100644
--- a/erpnext/selling/doctype/lead_source/lead_source.json
+++ b/erpnext/selling/doctype/lead_source/lead_source.json
@@ -1,7 +1,7 @@
{
"allow_copy": 0,
"allow_import": 0,
- "allow_rename": 0,
+ "allow_rename": 1,
"autoname": "field:source_name",
"beta": 0,
"creation": "2016-09-16 01:47:47.382372",
@@ -74,7 +74,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-09-16 02:03:01.441622",
+ "modified": "2020-09-16 02:03:01.441622",
"modified_by": "Administrator",
"module": "Selling",
"name": "Lead Source",
@@ -128,4 +128,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py
index 0c85a1b..d3281f7 100644
--- a/erpnext/selling/doctype/product_bundle/product_bundle.py
+++ b/erpnext/selling/doctype/product_bundle/product_bundle.py
@@ -29,6 +29,7 @@
frappe.throw(_("Row #{0}: Child Item should not be a Product Bundle. Please remove Item {1} and Save").format(item.idx, frappe.bold(item.item_code)))
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 8fa56ac..a68b738 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1,7 +1,6 @@
{
"actions": [],
"allow_import": 1,
- "allow_workflow": 1,
"autoname": "naming_series:",
"creation": "2013-06-18 12:39:59",
"doctype": "DocType",
@@ -1461,7 +1460,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2020-07-18 05:13:06.680696",
+ "modified": "2020-07-31 14:13:17.962015",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
@@ -1535,7 +1534,7 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
- "title_field": "title",
+ "title_field": "customer",
"track_changes": 1,
"track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index ffb6635..f882898 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -888,6 +888,7 @@
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_supplier(doctype, txt, searchfield, start, page_len, filters):
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
if supp_master_name == "Supplier Name":
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index f7b7ed8..83bd71d 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -14,10 +14,9 @@
def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None):
data = dict()
warehouse = ""
- display_items_in_stock = 0
if pos_profile:
- warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock'])
+ warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse'])
if not frappe.db.exists('Item Group', item_group):
item_group = get_root_of('Item Group')
@@ -85,7 +84,7 @@
item_price = item_prices.get(item_code) or {}
item_stock_qty = get_stock_availability(item_code, warehouse)
- if display_items_in_stock and not item_stock_qty:
+ if not item_stock_qty:
pass
else:
row = {}
@@ -160,6 +159,7 @@
return cond % tuple(item_groups)
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_group_query(doctype, txt, searchfield, start, page_len, filters):
item_groups = []
cond = "1=1"
@@ -179,12 +179,12 @@
@frappe.whitelist()
def check_opening_entry(user):
- open_vouchers = frappe.db.get_all("POS Opening Entry",
- filters = {
- "user": user,
+ open_vouchers = frappe.db.get_all("POS Opening Entry",
+ filters = {
+ "user": user,
"pos_closing_entry": ["in", ["", None]],
"docstatus": 1
- },
+ },
fields = ["name", "company", "pos_profile", "period_start_date"],
order_by = "period_start_date desc"
)
@@ -229,7 +229,7 @@
invoice_list = frappe.db.get_all('POS Invoice', filters={
'status': status
}, fields=fields)
-
+
return invoice_list
@frappe.whitelist()
@@ -244,7 +244,7 @@
if fieldname == 'email_id':
contact_doc.set('email_ids', [{ 'email_id': value, 'is_primary': 1}])
frappe.db.set_value('Customer', customer, 'email_id', value)
- elif fieldname == 'mobile_no':
+ elif fieldname == 'mobile_no':
contact_doc.set('phone_nos', [{ 'phone': value, 'is_primary_mobile_no': 1}])
frappe.db.set_value('Customer', customer, 'mobile_no', value)
contact_doc.save()
\ No newline at end of file
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
index 7e8e6e9..f5feb95 100644
--- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
@@ -96,7 +96,7 @@
# prepare data for report view
row["qty_to_bill"] = flt(row["qty"]) - flt(row["billed_qty"])
- row["delay"] = 0 if row["delay"] < 0 else row["delay"]
+ row["delay"] = 0 if row["delay"] and row["delay"] < 0 else row["delay"]
if filters.get("group_by_so"):
so_name = row["sales_order"]
diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py
index b29c305..96e6093 100644
--- a/erpnext/setup/doctype/party_type/party_type.py
+++ b/erpnext/setup/doctype/party_type/party_type.py
@@ -10,6 +10,7 @@
pass
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_party_type(doctype, txt, searchfield, start, page_len, filters):
cond = ''
if filters and filters.get('account'):
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
index 14500ba..21fa4c3 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
@@ -12,5 +12,11 @@
if (frm.doc.enabled === 1) {
frm.set_value('enable_variants', 1);
}
+ else {
+ frm.set_value('company', '');
+ frm.set_value('price_list', '');
+ frm.set_value('default_customer_group', '');
+ frm.set_value('quotation_series', '');
+ }
}
});
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
index c574afa..32004ef 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
@@ -95,15 +95,16 @@
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
+ "mandatory_depends_on": "eval: doc.enabled === 1",
"options": "Company",
- "remember_last_selected_value": 1,
- "reqd": 1
+ "remember_last_selected_value": 1
},
{
"description": "Prices will not be shown if Price List is not set",
"fieldname": "price_list",
"fieldtype": "Link",
"label": "Price List",
+ "mandatory_depends_on": "eval: doc.enabled === 1",
"options": "Price List"
},
{
@@ -115,14 +116,14 @@
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Default Customer Group",
- "options": "Customer Group",
- "reqd": 1
+ "mandatory_depends_on": "eval: doc.enabled === 1",
+ "options": "Customer Group"
},
{
"fieldname": "quotation_series",
"fieldtype": "Select",
"label": "Quotation Series",
- "reqd": 1
+ "mandatory_depends_on": "eval: doc.enabled === 1"
},
{
"collapsible": 1,
@@ -171,7 +172,7 @@
"idx": 1,
"issingle": 1,
"links": [],
- "modified": "2020-07-17 17:53:22.667228",
+ "modified": "2020-08-02 18:21:43.873303",
"modified_by": "Administrator",
"module": "Shopping Cart",
"name": "Shopping Cart Settings",
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 735f35f..38e5fe5 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -117,7 +117,7 @@
const stock_exists = (frm.doc.__onload
&& frm.doc.__onload.stock_exists) ? 1 : 0;
- ['is_stock_item', 'has_serial_no', 'has_batch_no'].forEach((fieldname) => {
+ ['is_stock_item', 'has_serial_no', 'has_batch_no', 'has_variants'].forEach((fieldname) => {
frm.set_df_property(fieldname, 'read_only', stock_exists);
});
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 963c87a..45526a3 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -473,6 +473,7 @@
},
{
"default": "0",
+ "depends_on": "has_batch_no",
"fieldname": "retain_sample",
"fieldtype": "Check",
"label": "Retain Sample"
@@ -499,7 +500,7 @@
"oldfieldtype": "Select"
},
{
- "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
+ "depends_on": "has_serial_no",
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
"fieldname": "serial_no_series",
"fieldtype": "Data",
@@ -1061,7 +1062,7 @@
"image_field": "image",
"links": [],
"max_attachments": 1,
- "modified": "2020-06-30 12:01:07.534447",
+ "modified": "2020-07-31 21:21:10.956453",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py
index 522dfc6..190cb62 100644
--- a/erpnext/stock/doctype/item_alternative/item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/item_alternative.py
@@ -43,6 +43,7 @@
frappe.throw(_("Already record exists for the item {0}").format(self.item_code))
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_alternative_items(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" (select alternative_item_code from `tabItem Alternative`
where item_code = %(item_code)s and alternative_item_code like %(txt)s)
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 25f1ed9..335175f 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -370,6 +370,7 @@
return supplier_items
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, page_len, filters):
conditions = ""
if txt:
@@ -403,6 +404,7 @@
return material_requests
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
doc = frappe.get_doc("Material Request", filters.get("doc"))
item_list = []
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index 4f831d7..a7a29cc 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -176,6 +176,7 @@
self.update_item_details()
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_details(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
return frappe.db.sql("""select name, item_name, description from `tabItem`
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index 568e742..c3bb514 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -59,6 +59,7 @@
(quality_inspection, self.modified, self.reference_name, self.item_code))
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def item_query(doctype, txt, searchfield, start, page_len, filters):
if filters.get("from"):
from frappe.desk.reportview import get_match_cond
@@ -88,6 +89,7 @@
{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all('Quality Inspection',
limit_start=start,
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 3b49c4c..1cc600b 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -45,7 +45,6 @@
"oldfieldtype": "Section Break"
},
{
- "description": "If blank, parent Warehouse Account or company default will be considered",
"fieldname": "warehouse_name",
"fieldtype": "Data",
"label": "Warehouse Name",
@@ -86,6 +85,7 @@
"fieldtype": "Column Break"
},
{
+ "description": "If blank, parent Warehouse Account or company default will be considered in transactions",
"fieldname": "account",
"fieldtype": "Link",
"label": "Account",
@@ -236,7 +236,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
- "modified": "2020-07-16 15:43:50.653256",
+ "modified": "2020-08-03 18:41:52.442502",
"modified_by": "Administrator",
"module": "Stock",
"name": "Warehouse",
diff --git a/erpnext/templates/generators/item/item_configure.js b/erpnext/templates/generators/item/item_configure.js
index 163c955..5fd9011 100644
--- a/erpnext/templates/generators/item/item_configure.js
+++ b/erpnext/templates/generators/item/item_configure.js
@@ -193,17 +193,14 @@
filtered_items_count === 1 ?
filtered_items[0] : '';
- // Allow Add to Cart if adding out of stock items enabled in Shopping Cart else check stock.
- const in_stock = product_info.allow_items_not_in_stock ? 1 : product_info.in_stock;
- const add_to_cart = `<a href data-action="btn_add_to_cart" data-item-code="${one_item}">${__('Add to cart')}</a>`;
- const product_action = in_stock ? add_to_cart : `<a style="color:#74808b;">${__('Not in Stock')}</a>`;
-
const item_add_to_cart = one_item ? `
<div class="alert alert-success d-flex justify-content-between align-items-center" role="alert">
<div>
<div>${one_item} ${product_info && product_info.price ? '(' + product_info.price.formatted_price_sales_uom + ')' : ''}</div>
</div>
- ${product_action}
+ <a href data-action="btn_add_to_cart" data-item-code="${one_item}">
+ ${__('Add to cart')}
+ </a>
</div>
`: '';
diff --git a/yarn.lock b/yarn.lock
index c5509d6..b19f566 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1084,9 +1084,9 @@
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.7.14:
- version "4.17.15"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
- integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+ version "4.17.19"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
+ integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
lowercase-keys@^1.0.0:
version "1.0.1"