From 513099d6240d253b83ca3fb993cd33f3becc4a2a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 17 May 2020 23:26:37 +0530 Subject: [PATCH 01/74] fix: Description for various fields --- .../loan_management/loan_management.json | 4 +- .../loan_application/loan_application.js | 23 ++++--- .../loan_interest_accrual.py | 65 ++++++++++--------- .../loan_repayment/loan_repayment.json | 4 +- .../loan_security_pledge.js | 23 ++++--- .../loan_security_type.json | 4 +- .../doctype/loan_type/loan_type.json | 7 +- 7 files changed, 72 insertions(+), 58 deletions(-) diff --git a/erpnext/loan_management/desk_page/loan_management/loan_management.json b/erpnext/loan_management/desk_page/loan_management/loan_management.json index f9ea978ed6..6cabff9443 100644 --- a/erpnext/loan_management/desk_page/loan_management/loan_management.json +++ b/erpnext/loan_management/desk_page/loan_management/loan_management.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, @@ -37,7 +37,7 @@ "idx": 0, "is_standard": 1, "label": "Loan Management", - "modified": "2020-04-02 11:28:51.380509", + "modified": "2020-05-16 08:01:27.784621", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Management", diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js index 6cf47bf85c..b56fce1d7c 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('Loan Application', { 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 094b9c698c..9b486e805d 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 @@ class LoanInterestAccrual(AccountsController): 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): @@ -38,37 +38,38 @@ class LoanInterestAccrual(AccountsController): 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 789c129946..5942455919 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 82837b3dac..11c932ff1c 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('Loan Security Pledge', { 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_type/loan_security_type.json b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json index f46b88cbca..871e82563a 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 51c5cb98a6..90ae3b01bd 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.json +++ b/erpnext/loan_management/doctype/loan_type/loan_type.json @@ -75,6 +75,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", @@ -82,6 +83,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", @@ -93,6 +95,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", @@ -100,6 +103,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", @@ -108,6 +112,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" @@ -143,7 +148,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-04-15 00:24:43.259963", + "modified": "2020-05-16 09:08:09.029921", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Type", From 5ccefdc08a1bbbfc0ff24b8f1ca3de835a4f52a9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 17 May 2020 23:26:59 +0530 Subject: [PATCH 02/74] fix: Patch to update old loans --- erpnext/patches.txt | 1 + erpnext/patches/v13_0/update_old_loans.py | 83 +++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 erpnext/patches/v13_0/update_old_loans.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ce0e4ac471..f3907f4b17 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -680,3 +680,4 @@ erpnext.patches.v12_0.fix_quotation_expired_status erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry erpnext.patches.v12_0.retain_permission_rules_for_video_doctype erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive +erpnext.patches.v13_0.update_old_loans 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 0000000000..e924f6234b --- /dev/null +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -0,0 +1,83 @@ +from __future__ import unicode_literals +import frappe +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') + + parent_income = 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=parent_income) + + 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() + From a96a16cf59ab21dbae813a4f868f97b3c33c8a0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2020 11:07:58 +0000 Subject: [PATCH 03/74] build(deps): bump lodash from 4.17.15 to 4.17.19 Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c5509d6e1a..b19f566fd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1084,9 +1084,9 @@ lodash.set@^4.3.2: 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" From f4a7adbf2eae6f4d97d1b0411c60daa5457ae4ba Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 22 Jul 2020 18:59:04 +0530 Subject: [PATCH 04/74] refactor: Education Desk Page --- .../desk_page/education/education.json | 124 +++-- .../doctype/instructor/instructor.json | 430 ++++-------------- .../education/education.json | 20 + 3 files changed, 208 insertions(+), 366 deletions(-) create mode 100644 erpnext/education/education_dashboard/education/education.json diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json index b341ec4b99..f17c4f40cc 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]" }, { "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,8 +57,13 @@ }, { "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", @@ -79,10 +74,11 @@ "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-22 18:56:12.276117", "modified_by": "Administrator", "module": "Education", "name": "Education", @@ -90,5 +86,63 @@ "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/instructor/instructor.json b/erpnext/education/doctype/instructor/instructor.json index 5367c0e66f..632b29cd1f 100644 --- a/erpnext/education/doctype/instructor/instructor.json +++ b/erpnext/education/doctype/instructor/instructor.json @@ -1,348 +1,116 @@ { - "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", + "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" } - ], - "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-22 18:55:43.699989", + "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/education_dashboard/education/education.json b/erpnext/education/education_dashboard/education/education.json new file mode 100644 index 0000000000..77a334057a --- /dev/null +++ b/erpnext/education/education_dashboard/education/education.json @@ -0,0 +1,20 @@ +{ + "cards": [], + "charts": [ + { + "width": "Half" + } + ], + "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-07-22 18:51:02.195762", + "modified_by": "Administrator", + "module": "Education", + "name": "Education", + "owner": "Administrator" +} \ No newline at end of file From 49140ccbfd3bebdc7a9971aae0382aa2476a1a33 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 27 Jul 2020 18:48:15 +0530 Subject: [PATCH 05/74] feat: Program wise Fee Collection Query Report --- .../program_wise_fee_collection/__init__.py | 0 .../program_wise_fee_collection.json | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 erpnext/education/report/program_wise_fee_collection/__init__.py create mode 100644 erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.json 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 0000000000..e69de29bb2 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 0000000000..6b7a9754f1 --- /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-07-27 18:00:22.852723", + "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": "Query Report", + "roles": [ + { + "role": "Academics User" + }, + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + } + ] +} \ No newline at end of file From 6c11f26a117f4af3a6c30002c26cd21ce1b4c1e9 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 27 Jul 2020 18:50:04 +0530 Subject: [PATCH 06/74] feat: Education dashboard charts and number cards --- .../course_wise_enrollment.json | 31 + .../course_wise_student_count.json | 31 + .../instructor_gender_diversity_ratio.json | 31 + .../program_enrollments.json | 30 + .../program_wise_enrollment.json | 31 + .../program_wise_fee_collection.json | 31 + ...ent_category_wise_program_enrollments.json | 31 + .../student_gender_diversity_ratio.json | 30 + .../desk_page/education/education.json | 11 +- .../doctype/instructor/instructor.json | 11 +- .../education/doctype/student/student.json | 1558 +++-------------- .../education/education.json | 46 +- .../program_enrollments.json | 23 + .../student_applicants_to_review.json | 23 + .../total_instructors/total_instructors.json | 23 + .../total_students/total_students.json | 23 + .../course_wise_assessment_report.py | 4 +- 17 files changed, 657 insertions(+), 1311 deletions(-) create mode 100644 erpnext/education/dashboard_chart/course_wise_enrollment/course_wise_enrollment.json create mode 100644 erpnext/education/dashboard_chart/course_wise_student_count/course_wise_student_count.json create mode 100644 erpnext/education/dashboard_chart/instructor_gender_diversity_ratio/instructor_gender_diversity_ratio.json create mode 100644 erpnext/education/dashboard_chart/program_enrollments/program_enrollments.json create mode 100644 erpnext/education/dashboard_chart/program_wise_enrollment/program_wise_enrollment.json create mode 100644 erpnext/education/dashboard_chart/program_wise_fee_collection/program_wise_fee_collection.json create mode 100644 erpnext/education/dashboard_chart/student_category_wise_program_enrollments/student_category_wise_program_enrollments.json create mode 100644 erpnext/education/dashboard_chart/student_gender_diversity_ratio/student_gender_diversity_ratio.json create mode 100644 erpnext/education/number_card/program_enrollments/program_enrollments.json create mode 100644 erpnext/education/number_card/student_applicants_to_review/student_applicants_to_review.json create mode 100644 erpnext/education/number_card/total_instructors/total_instructors.json create mode 100644 erpnext/education/number_card/total_students/total_students.json 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 0000000000..9c5f784648 --- /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 0000000000..5441518def --- /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 0000000000..b7ee509b92 --- /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 0000000000..2a4a4a3e0c --- /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 0000000000..2ba138e332 --- /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 0000000000..62f453d29d --- /dev/null +++ b/erpnext/education/dashboard_chart/program_wise_fee_collection/program_wise_fee_collection.json @@ -0,0 +1,31 @@ +{ + "chart_name": "Program wise Fee Collection", + "chart_type": "Report", + "creation": "2020-07-27 16:19:03.077317", + "docstatus": 0, + "doctype": "Dashboard Chart", + "dynamic_filters_json": "{}", + "filters_json": "{}", + "group_by_type": "Count", + "idx": 0, + "is_public": 1, + "is_standard": 1, + "modified": "2020-07-27 16:19:11.333532", + "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": 0, + "x_field": "Program", + "y_axis": [ + { + "y_field": "Fees Collected" + } + ] +} \ 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 0000000000..88871457ec --- /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 0000000000..ce602d29ee --- /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 f17c4f40cc..cf04b2ffb2 100644 --- a/erpnext/education/desk_page/education/education.json +++ b/erpnext/education/desk_page/education/education.json @@ -28,7 +28,7 @@ { "hidden": 0, "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]" + "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, @@ -67,7 +67,12 @@ } ], "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, @@ -78,7 +83,7 @@ "idx": 0, "is_standard": 1, "label": "Education", - "modified": "2020-07-22 18:56:12.276117", + "modified": "2020-07-27 17:50:13.745212", "modified_by": "Administrator", "module": "Education", "name": "Education", diff --git a/erpnext/education/doctype/instructor/instructor.json b/erpnext/education/doctype/instructor/instructor.json index 632b29cd1f..a417391711 100644 --- a/erpnext/education/doctype/instructor/instructor.json +++ b/erpnext/education/doctype/instructor/instructor.json @@ -9,6 +9,7 @@ "field_order": [ "instructor_name", "employee", + "gender", "column_break_5", "status", "naming_series", @@ -77,11 +78,19 @@ "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" } ], "image_field": "image", "links": [], - "modified": "2020-07-22 18:55:43.699989", + "modified": "2020-07-23 18:33:57.904398", "modified_by": "Administrator", "module": "Education", "name": "Instructor", diff --git a/erpnext/education/doctype/student/student.json b/erpnext/education/doctype/student/student.json index bee915e91d..ac65c0cd7b 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/education_dashboard/education/education.json b/erpnext/education/education_dashboard/education/education.json index 77a334057a..6d9f2de360 100644 --- a/erpnext/education/education_dashboard/education/education.json +++ b/erpnext/education/education_dashboard/education/education.json @@ -1,8 +1,50 @@ { - "cards": [], + "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", @@ -12,7 +54,7 @@ "idx": 0, "is_default": 0, "is_standard": 1, - "modified": "2020-07-22 18:51:02.195762", + "modified": "2020-07-27 18:42:42.872547", "modified_by": "Administrator", "module": "Education", "name": "Education", 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 0000000000..5847679ddd --- /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 0000000000..258667a2d4 --- /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 0000000000..b8d3cc0fdf --- /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 0000000000..109c3d8ad9 --- /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/report/course_wise_assessment_report/course_wise_assessment_report.py b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py index ce581486ec..cd1dcc123b 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py @@ -42,7 +42,7 @@ def execute(filters=None): # create the list of possible grades if student_row[scrub_criteria] not in grades: grades.append(student_row[scrub_criteria]) - + # create the dict of for gradewise analysis if student_row[scrub_criteria] not in grade_wise_analysis[criteria]: grade_wise_analysis[criteria][student_row[scrub_criteria]] = 1 @@ -152,7 +152,7 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False, elif create_total_dict: if get_all_assessment_groups: formatted_assessment_result[result.student][result.course][result.assessment_group]\ - [result.assessment_criteria] = assessment_criteria_details + [result.assessment_criteria] = assessment_criteria_details if not formatted_assessment_result[result.student][result.course][args.assessment_group]: formatted_assessment_result[result.student][result.course][args.assessment_group] = defaultdict(dict) formatted_assessment_result[result.student][result.course][args.assessment_group]\ From 9a2cc74414ef7e54d0eb863f1d64603b910f3ee6 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 27 Jul 2020 21:33:00 +0530 Subject: [PATCH 07/74] feat: onboarding for Education module --- .../desk_page/education/education.json | 3 +- .../education/education.json | 50 +++++++++++++++++++ .../create_a_course/create_a_course.json | 19 +++++++ .../create_a_program/create_a_program.json | 19 +++++++ .../create_a_student/create_a_student.json | 19 +++++++ .../create_a_topic/create_a_topic.json | 19 +++++++ .../create_an_instructor.json | 19 +++++++ .../enroll_a_student_in_a_program.json | 19 +++++++ .../introduction_to_program_and_courses.json | 19 +++++++ .../introduction_to_student_attendance.json | 19 +++++++ .../introduction_to_student_group.json | 20 ++++++++ 11 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 erpnext/education/module_onboarding/education/education.json create mode 100644 erpnext/education/onboarding_step/create_a_course/create_a_course.json create mode 100644 erpnext/education/onboarding_step/create_a_program/create_a_program.json create mode 100644 erpnext/education/onboarding_step/create_a_student/create_a_student.json create mode 100644 erpnext/education/onboarding_step/create_a_topic/create_a_topic.json create mode 100644 erpnext/education/onboarding_step/create_an_instructor/create_an_instructor.json create mode 100644 erpnext/education/onboarding_step/enroll_a_student_in_a_program/enroll_a_student_in_a_program.json create mode 100644 erpnext/education/onboarding_step/introduction_to_program_and_courses/introduction_to_program_and_courses.json create mode 100644 erpnext/education/onboarding_step/introduction_to_student_attendance/introduction_to_student_attendance.json create mode 100644 erpnext/education/onboarding_step/introduction_to_student_group/introduction_to_student_group.json diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json index cf04b2ffb2..77ee8ecaf6 100644 --- a/erpnext/education/desk_page/education/education.json +++ b/erpnext/education/desk_page/education/education.json @@ -83,10 +83,11 @@ "idx": 0, "is_standard": 1, "label": "Education", - "modified": "2020-07-27 17:50:13.745212", + "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, diff --git a/erpnext/education/module_onboarding/education/education.json b/erpnext/education/module_onboarding/education/education.json new file mode 100644 index 0000000000..885902e4cf --- /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": "Student, Instructors, Programs and more.", + "success_message": "The Education Module is all set up!", + "title": "Let's Set Up the Education Module." +} \ 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 0000000000..02eee14056 --- /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 0000000000..61726304e0 --- /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 0000000000..07c3f7331e --- /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 0000000000..96a536488e --- /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 0000000000..419d6e07f1 --- /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 0000000000..61e48cd520 --- /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 0000000000..a9ddfc00da --- /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 0000000000..3de99728ea --- /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 0000000000..74bdcd17be --- /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 From 7cbc7946af0e2b8506657583ebfb07579a39c7fc Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 28 Jul 2020 14:11:12 +0530 Subject: [PATCH 08/74] fix: validate check out and check in time for inpatient occupancy --- .../doctype/inpatient_record/inpatient_record.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py index cf63b65f4d..cbcb24faee 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, json from frappe import _ -from frappe.utils import today, now_datetime, getdate +from frappe.utils import today, now_datetime, getdate, get_datetime from frappe.model.document import Document from frappe.desk.reportview import get_match_cond @@ -30,6 +30,11 @@ class InpatientRecord(Document): (getdate(self.discharge_ordered_date) < getdate(self.scheduled_date)): frappe.throw(_('Expected and Discharge dates cannot be less than Admission Schedule date')) + for entry in self.inpatient_occupancies: + if entry.check_in and entry.check_out and \ + get_datetime(entry.check_in) > get_datetime(entry.check_out): + frappe.throw(_('Check Out datetime cannot be less than Check In datetime for entry #{0}').format(entry.idx)) + def validate_already_scheduled_or_admitted(self): query = """ select name, status From a695971596d715f14c537ad4960af148336a157b Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 28 Jul 2020 20:15:29 +0530 Subject: [PATCH 09/74] fix: show the standard validation message Co-authored-by: Marica --- erpnext/healthcare/doctype/inpatient_record/inpatient_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py index cbcb24faee..69356baad5 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -33,7 +33,7 @@ class InpatientRecord(Document): for entry in self.inpatient_occupancies: if entry.check_in and entry.check_out and \ get_datetime(entry.check_in) > get_datetime(entry.check_out): - frappe.throw(_('Check Out datetime cannot be less than Check In datetime for entry #{0}').format(entry.idx)) + frappe.throw(_('Row #{0}: Check Out datetime cannot be less than Check In datetime').format(entry.idx)) def validate_already_scheduled_or_admitted(self): query = """ From 8cfa00920ed53f44bc9cb8ba05b46ca5778b376d Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 29 Jul 2020 15:24:03 +0530 Subject: [PATCH 10/74] fix: cannot submit value adjustment with custom dimension --- .../asset_value_adjustment.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 155597e856..fd702c74c7 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -8,6 +8,7 @@ from frappe import _ from frappe.utils import flt, getdate, cint, date_diff, formatdate from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from frappe.model.document import Document +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts class AssetValueAdjustment(Document): def validate(self): @@ -53,17 +54,33 @@ class AssetValueAdjustment(Document): je.company = self.company je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount) - je.append("accounts", { + credit_entry = { "account": accumulated_depreciation_account, "credit_in_account_currency": self.difference_amount, "cost_center": depreciation_cost_center or self.cost_center - }) + } - je.append("accounts", { + debit_entry = { "account": depreciation_expense_account, "debit_in_account_currency": self.difference_amount, "cost_center": depreciation_cost_center or self.cost_center - }) + } + + accounting_dimensions = get_checks_for_pl_and_bs_accounts() + + for dimension in accounting_dimensions: + if dimension.get('mandatory_for_bs'): + credit_entry.update({ + dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') + }) + + if dimension.get('mandatory_for_pl'): + debit_entry.update({ + dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') + }) + + je.append("accounts", credit_entry) + je.append("accounts", debit_entry) je.flags.ignore_permissions = True je.submit() From 031768f49d3cae952ac46b11d000aea90776223f Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 30 Jul 2020 12:40:53 +0530 Subject: [PATCH 11/74] chore: asset form reorder (#22833) Co-authored-by: Marica --- erpnext/assets/doctype/asset/asset.json | 74 +++++++++++++++++-------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 97165a31d2..a3152abf20 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "naming_series:", @@ -7,8 +8,9 @@ "document_type": "Document", "engine": "InnoDB", "field_order": [ + "is_existing_asset", + "section_break_2", "naming_series", - "asset_name", "item_code", "item_name", "asset_category", @@ -17,29 +19,31 @@ "supplier", "customer", "image", - "purchase_invoice", + "journal_entry_for_scrap", "column_break_3", "company", + "asset_name", "location", "custodian", "department", - "purchase_date", "disposal_date", - "journal_entry_for_scrap", - "purchase_receipt", "accounting_dimensions_section", "cost_center", "dimension_col_break", - "section_break_5", - "gross_purchase_amount", + "purchase_details_section", + "purchase_receipt", + "purchase_invoice", "available_for_use_date", - "column_break_18", + "column_break_23", + "gross_purchase_amount", + "purchase_date", + "section_break_23", "calculate_depreciation", "allow_monthly_depreciation", - "is_existing_asset", + "column_break_33", "opening_accumulated_depreciation", "number_of_depreciations_booked", - "section_break_23", + "section_break_36", "finance_books", "section_break_33", "depreciation_method", @@ -64,7 +68,6 @@ "status", "booked_fixed_asset", "column_break_51", - "purchase_receipt_amount", "default_finance_book", "amended_from" @@ -187,6 +190,8 @@ "fieldname": "purchase_date", "fieldtype": "Date", "label": "Purchase Date", + "read_only": 1, + "read_only_depends_on": "eval:!doc.is_existing_asset", "reqd": 1 }, { @@ -204,25 +209,20 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "section_break_5", - "fieldtype": "Section Break" - }, { "fieldname": "gross_purchase_amount", "fieldtype": "Currency", "label": "Gross Purchase Amount", "options": "Company:company:default_currency", + "read_only": 1, + "read_only_depends_on": "eval:!doc.is_existing_asset", "reqd": 1 }, { "fieldname": "available_for_use_date", "fieldtype": "Date", - "label": "Available-for-use Date" - }, - { - "fieldname": "column_break_18", - "fieldtype": "Column Break" + "label": "Available-for-use Date", + "reqd": 1 }, { "default": "0", @@ -252,12 +252,14 @@ "no_copy": 1 }, { - "depends_on": "calculate_depreciation", + "collapsible": 1, + "collapsible_depends_on": "eval:doc.calculate_depreciation || doc.is_existing_asset", "fieldname": "section_break_23", "fieldtype": "Section Break", "label": "Depreciation" }, { + "columns": 10, "fieldname": "finance_books", "fieldtype": "Table", "label": "Finance Books", @@ -305,8 +307,7 @@ { "depends_on": "calculate_depreciation", "fieldname": "section_break_14", - "fieldtype": "Section Break", - "label": "Depreciation Schedule" + "fieldtype": "Section Break" }, { "fieldname": "schedules", @@ -456,12 +457,37 @@ "fieldname": "allow_monthly_depreciation", "fieldtype": "Check", "label": "Allow Monthly Depreciation" + }, + { + "fieldname": "section_break_2", + "fieldtype": "Section Break" + }, + { + "collapsible": 1, + "collapsible_depends_on": "is_existing_asset", + "fieldname": "purchase_details_section", + "fieldtype": "Section Break", + "label": "Purchase Details" + }, + { + "fieldname": "column_break_23", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_33", + "fieldtype": "Column Break" + }, + { + "depends_on": "calculate_depreciation", + "fieldname": "section_break_36", + "fieldtype": "Section Break" } ], "idx": 72, "image_field": "image", "is_submittable": 1, - "modified": "2019-10-22 15:47:36.050828", + "links": [], + "modified": "2020-07-28 15:04:44.452224", "modified_by": "Administrator", "module": "Assets", "name": "Asset", From 621529adfbf5fb2e1ab1161f6e6d99a275e28ae7 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 30 Jul 2020 13:18:41 +0530 Subject: [PATCH 12/74] fix: unlink item from healthcare service unit type (#22828) Co-authored-by: Marica --- .../healthcare_service_unit_type.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py index bb86eaacc4..a318e50600 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py @@ -39,7 +39,9 @@ class HealthcareServiceUnitType(Document): def on_trash(self): if self.item: try: - frappe.delete_doc('Item', self.item) + item = self.item + self.db_set('item', '') + frappe.delete_doc('Item', item) except Exception: frappe.throw(_('Not permitted. Please disable the Service Unit Type')) From 9087689d90b950d3fe39dc6f5f4517337f8fcc68 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 30 Jul 2020 16:10:05 +0530 Subject: [PATCH 13/74] fix: subtitle for onboarding Co-authored-by: Marica --- erpnext/education/module_onboarding/education/education.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/education/module_onboarding/education/education.json b/erpnext/education/module_onboarding/education/education.json index 885902e4cf..e5f0fec3d1 100644 --- a/erpnext/education/module_onboarding/education/education.json +++ b/erpnext/education/module_onboarding/education/education.json @@ -44,7 +44,7 @@ "step": "Introduction to Student Attendance" } ], - "subtitle": "Student, Instructors, Programs and more.", + "subtitle": "Students, Instructors, Programs and more.", "success_message": "The Education Module is all set up!", "title": "Let's Set Up the Education Module." -} \ No newline at end of file +} From a14618efe401c488599860b03ae5a1829cae78ed Mon Sep 17 00:00:00 2001 From: Saurabh Date: Thu, 30 Jul 2020 17:22:29 +0530 Subject: [PATCH 14/74] fix: validate theme_scss attribute --- erpnext/public/js/website_theme.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/website_theme.js b/erpnext/public/js/website_theme.js index 84de2f5b51..9662f78538 100644 --- a/erpnext/public/js/website_theme.js +++ b/erpnext/public/js/website_theme.js @@ -4,8 +4,8 @@ frappe.ui.form.on('Website Theme', { validate(frm) { let theme_scss = frm.doc.theme_scss; - if (theme_scss.includes('frappe/public/scss/website') - && !theme_scss.includes('erpnext/public/scss/website') + if (theme_scss && (theme_scss.includes('frappe/public/scss/website') + && !theme_scss.includes('erpnext/public/scss/website')) ) { frm.set_value('theme_scss', `${frm.doc.theme_scss}\n@import "erpnext/public/scss/website";`); From 9837285bf1e77463e2e3e76f6e2f2d10146f9030 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 30 Jul 2020 20:52:20 +0530 Subject: [PATCH 15/74] fix: Ignore cancelled gl entries to get account balance --- erpnext/accounts/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 824b2f2efb..51ac7cfbfa 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -122,7 +122,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company 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 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company 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: From cf00ee49ec2b5a72d6319890899071724164ab71 Mon Sep 17 00:00:00 2001 From: Marica Date: Fri, 31 Jul 2020 15:14:50 +0530 Subject: [PATCH 16/74] fix: PO/SO view title (#22858) --- erpnext/buying/doctype/purchase_order/purchase_order.json | 4 ++-- erpnext/selling/doctype/sales_order/sales_order.json | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 502dbba571..4201e0b635 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/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 8fa56ac959..a68b7387b7 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 From 2a4c90302b7597927d39039aeb8376e498f84fbb Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Fri, 31 Jul 2020 17:59:30 +0530 Subject: [PATCH 17/74] fix: minor recritment analytics fixes (#22830) Co-authored-by: Rucha Mahabal --- .../recruitment_analytics.py | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py index 867209436c..e961114ac2 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_data(filters): 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_applicant(jo_list): 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(): From dcb462f3058266fbf9b73955ff964787b4cca7e4 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 1 Aug 2020 13:47:09 +0530 Subject: [PATCH 18/74] fix: Import pycountry and taxjar only if taxjar is enabled --- erpnext/erpnext_integrations/taxjar_integration.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 633692dd24..24fc3d44b9 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 get_client(): def create_transaction(doc, method): + import taxjar """Create an order transaction in TaxJar""" if not TAXJAR_CREATE_TRANSACTIONS: @@ -208,6 +206,7 @@ def get_shipping_address_details(doc): 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")) From b9dc21129c95df9774fbf09627afefd0e6496d47 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 1 Aug 2020 22:51:40 +0530 Subject: [PATCH 19/74] fix: Loan Seurity shortfall calculation fixes --- .../loan_management/doctype/loan/loan.json | 4 +- .../loan_management/doctype/loan/test_loan.py | 2 +- .../loan_security_pledge.py | 22 ++++++++++ .../loan_security_shortfall.py | 44 ++++++++++--------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 192beee7e3..aa5e21b426 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 c65996e65f..23815d5982 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -269,7 +269,7 @@ class TestLoan(unittest.TestCase): 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_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py index 961c05c9c1..2bb6fd84e5 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 @@ class LoanSecurityPledge(Document): 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 @@ class LoanSecurityPledge(Document): 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 ffd96737a5..24527a17b8 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 @@ import frappe 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,29 @@ def check_for_ltv_shortfall(process_loan_security_shortfall): "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'}) 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 +84,14 @@ def create_loan_security_shortfall(loan, value, process_loan_security_shortfall) 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 + From d909669a18c39098db734ad3b6b0a1c5b7789f74 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 2 Aug 2020 17:00:53 +0530 Subject: [PATCH 20/74] fix: Test cases --- .../doctype/loan_security_shortfall/loan_security_shortfall.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 24527a17b8..aae68df93a 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 @@ -51,7 +51,8 @@ def check_for_ltv_shortfall(process_loan_security_shortfall): "valid_upto": (">=", update_time) }, as_list=1)) - loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'], filters={'status': 'Disbursed'}) + loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'], + filters={'status': 'Disbursed', 'is_secured': 1}) loan_security_map = {} From 4104887abb6a3a50a529831ad25d63aae081463a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 2 Aug 2020 18:23:54 +0530 Subject: [PATCH 21/74] fix: fieldname in filter --- .../doctype/loan_security_shortfall/loan_security_shortfall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 aae68df93a..02efe240bd 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 @@ -52,7 +52,7 @@ def check_for_ltv_shortfall(process_loan_security_shortfall): }, as_list=1)) loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'], - filters={'status': 'Disbursed', 'is_secured': 1}) + filters={'status': 'Disbursed', 'is_secured_loan': 1}) loan_security_map = {} From ba52dd8ba6b36837fb7148714a0cf162b8b2ad2d Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 3 Aug 2020 08:57:49 +0530 Subject: [PATCH 22/74] fix: minor payroll_dashboard fixes (#22832) * fix: minor payroll_dashboard fixes * Update erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js Co-authored-by: Rucha Mahabal Co-authored-by: Nabin Hait Co-authored-by: Rucha Mahabal --- .../job_application_status/job_application_status.json | 6 +++--- .../monthly_attendance_sheet.js | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) 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 bfcfa96752..42a830970e 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/report/monthly_attendance_sheet/monthly_attendance_sheet.js b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js index 4b9b928640..42f7cdb50f 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 @@ frappe.query_reports["Monthly Attendance Sheet"] = { "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", From 4cc99286c07c1551139088bcf7a6290b73390de7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2020 09:33:31 +0530 Subject: [PATCH 23/74] fix: Update modified timestamp in accounts settings (#22873) --- .../accounts/doctype/accounts_settings/accounts_settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 8ca8b71ef8..b2e8b090c7 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", From 9cc2d340badf537294b3fd065ef4294777ea3e67 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2020 10:43:47 +0530 Subject: [PATCH 24/74] Reset home page based on product settings (#22875) --- erpnext/portal/doctype/products_settings/products_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/portal/doctype/products_settings/products_settings.py b/erpnext/portal/doctype/products_settings/products_settings.py index b984aeb67d..ae7dc68020 100644 --- a/erpnext/portal/doctype/products_settings/products_settings.py +++ b/erpnext/portal/doctype/products_settings/products_settings.py @@ -11,9 +11,9 @@ from frappe.model.document import Document 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() From 5e438cc853aa48e80c28b88eebcdcfce873c40af Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Mon, 3 Aug 2020 09:16:50 +0200 Subject: [PATCH 25/74] Update lead_source.json (#22872) Allow Lead Source to be renamed. This is usefull for cleaning up data at a later point and allow correcting spelling errors. Co-authored-by: Rucha Mahabal --- erpnext/selling/doctype/lead_source/lead_source.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/lead_source/lead_source.json b/erpnext/selling/doctype/lead_source/lead_source.json index 868f6d11d0..373e83af9c 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 +} From 5572f8eb1e09ba4428c79c0161ba3d69b6ab228b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 3 Aug 2020 13:40:11 +0530 Subject: [PATCH 26/74] fix: Test case for subscription --- .../accounts/doctype/subscription/test_subscription.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index f41f08a6c4..811fc356cf 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -7,8 +7,8 @@ import unittest 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 @@ class TestSubscription(unittest.TestCase): 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') From 1dfd9fd756aa006ce6ab304be99b46a15dd9ec7f Mon Sep 17 00:00:00 2001 From: Prssanna Desai Date: Mon, 3 Aug 2020 14:48:45 +0530 Subject: [PATCH 27/74] fix: check if row['delay'] exists (#22889) --- .../selling/report/sales_order_analysis/sales_order_analysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7e8e6e9e8b..f5feb95f1a 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 @@ def prepare_data(data, filters): # 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"] From dd97524db5bb277cb963bc6d5e0135a70837f906 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 3 Aug 2020 14:55:40 +0530 Subject: [PATCH 28/74] fix: Misleading description in Warehouse (#22877) Co-authored-by: Rucha Mahabal --- erpnext/stock/doctype/warehouse/warehouse.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index 3b49c4ca52..c0c9fbc92d 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", @@ -236,7 +235,7 @@ "idx": 1, "is_tree": 1, "links": [], - "modified": "2020-07-16 15:43:50.653256", + "modified": "2020-08-03 11:19:35.943330", "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", From b50b20458e76fd43a82a065b9cd217154a2eba48 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 3 Aug 2020 15:51:57 +0530 Subject: [PATCH 29/74] fix: TypeError while concatenating account number and name in COA (#22885) Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> --- .../doctype/account/chart_of_accounts/chart_of_accounts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1bf9196a4f..0e3b24cda3 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 @@ def build_tree_from_json(chart_template, chart_data=None): 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']) From 1895e9b89a52fd9ee0ddade238bd4c0e66438b60 Mon Sep 17 00:00:00 2001 From: Anupam Kumar Date: Mon, 3 Aug 2020 18:50:11 +0530 Subject: [PATCH 30/74] fix: Shopping cart issue v13 (#22868) * refactoring shopping cart settings * adding column_break in shopping cart settings * fix: mandatory depend on fix company * fix: resetting company, price_list, default_customer_group, quotation_series when card is diabled. --- .../shopping_cart_settings.js | 6 ++++++ .../shopping_cart_settings.json | 13 +++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) 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 14500ba6b3..21fa4c3065 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 @@ frappe.ui.form.on("Shopping Cart Settings", { 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 c574afa68c..32004efdca 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", From 101fe2b769e84c5348875b60527289b746c9c834 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 3 Aug 2020 19:42:24 +0530 Subject: [PATCH 31/74] fix: Assessment Result child table not visible when accessed via dashboard (#22880) Co-authored-by: Nabin Hait --- .../assessment_result/assessment_result.js | 11 +- .../assessment_result/assessment_result.json | 648 ++---------------- .../assessment_result_detail.json | 242 ++----- 3 files changed, 111 insertions(+), 790 deletions(-) diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js index 12fdd91c25..63d1aee0cb 100644 --- a/erpnext/education/doctype/assessment_result/assessment_result.js +++ b/erpnext/education/doctype/assessment_result/assessment_result.js @@ -6,10 +6,11 @@ frappe.ui.form.on('Assessment Result', { 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 @@ frappe.ui.form.on('Assessment Result', { }, 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 @@ frappe.ui.form.on('Assessment Result Detail', { 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 212d47cff0..7a893aabb8 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 85d943beaa..450f41cbbb 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 From 48163e31c54d8e3c1edb9ea082cfba0780d50579 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2020 20:38:28 +0530 Subject: [PATCH 32/74] Dunning cleanup (#22898) * fix: Dunning cleanup * fix: Added dashboard for Dunning --- erpnext/accounts/doctype/dunning/dunning.js | 19 ++++++++++++++++--- erpnext/accounts/doctype/dunning/dunning.json | 8 ++++---- erpnext/accounts/doctype/dunning/dunning.py | 16 +++++++++------- .../doctype/dunning/dunning_dashboard.py | 17 +++++++++++++++++ .../sales_invoice/sales_invoice_dashboard.py | 2 +- 5 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 erpnext/accounts/doctype/dunning/dunning_dashboard.py diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js index c563368894..9909c6c2ab 100644 --- a/erpnext/accounts/doctype/dunning/dunning.js +++ b/erpnext/accounts/doctype/dunning/dunning.js @@ -44,6 +44,19 @@ frappe.ui.form.on("Dunning", { ); 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 @@ frappe.ui.form.on("Dunning", { }, 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 b3eddf5f22..d55bfd1ac4 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 0be6a480c9..3e372affa1 100644 --- a/erpnext/accounts/doctype/dunning/dunning.py +++ b/erpnext/accounts/doctype/dunning/dunning.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals 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 @@ class Dunning(AccountsController): 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 @@ class Dunning(AccountsController): 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, @@ -91,9 +94,8 @@ def resolve_dunning(doc, state): def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days): interest_amount = 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 0000000000..19a73ddfa4 --- /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/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py index 4a8fcc03fd..f1069282ed 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 @@ def get_data(): 'transactions': [ { 'label': _('Payment'), - 'items': ['Payment Entry', 'Payment Request', 'Journal Entry', 'Invoice Discounting'] + 'items': ['Payment Entry', 'Payment Request', 'Journal Entry', 'Invoice Discounting', 'Dunning'] }, { 'label': _('Reference'), From e211bb7a538cde4208c84da2801ea9f69d4a24f4 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 3 Aug 2020 20:40:09 +0530 Subject: [PATCH 33/74] fix: Reposition description in Warehouse (#22895) --- erpnext/stock/doctype/warehouse/warehouse.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index c0c9fbc92d..1cc600b9ca 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.json +++ b/erpnext/stock/doctype/warehouse/warehouse.json @@ -85,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", @@ -235,7 +236,7 @@ "idx": 1, "is_tree": 1, "links": [], - "modified": "2020-08-03 11:19:35.943330", + "modified": "2020-08-03 18:41:52.442502", "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", From b7311c8fc1b4039a114dd0dfa5a3f1ba85f5f48c Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 3 Aug 2020 20:41:25 +0530 Subject: [PATCH 34/74] fix: SQL query in accounts receivable, payable reports (#22888) --- .../report/accounts_receivable/accounts_receivable.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 66aa18058b..59117c8174 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -643,8 +643,10 @@ class ReceivablePayableReport(object): 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"): From a042d4721eaadbb835ce114e66d9b15d01dfa100 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2020 20:42:15 +0530 Subject: [PATCH 35/74] fix: Bank Clearance of POS purchase invoice (#22882) --- .../doctype/bank_clearance/bank_clearance.py | 21 +++++++++++++++---- .../purchase_invoice/purchase_invoice.json | 8 ++++--- .../sales_invoice_payment.json | 3 ++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index 6fec3ab368..76d82e7339 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -60,12 +60,12 @@ class BankClearance(Document): """.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 @@ class BankClearance(Document): 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/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index df77dc8417..2e91c8ef19 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_payment/sales_invoice_payment.json b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json index 2f9d381c92..5ab46b7fd5 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", From d67c2ea0d4a75d09ed09814fdd6027377ce4e790 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 5 Aug 2020 14:13:14 +0530 Subject: [PATCH 36/74] fix: make program field mandatory in Fees --- erpnext/education/doctype/fees/fees.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/education/doctype/fees/fees.json b/erpnext/education/doctype/fees/fees.json index 99f9f4f4cd..0fb7672890 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", From 8edace1a5891c8d5dbb2eb9a835ea97242c8ff55 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 5 Aug 2020 16:24:21 +0530 Subject: [PATCH 37/74] fix: covert Program wise Fee Collection to a Script Report --- .../program_wise_fee_collection.json | 17 +-- .../education/education.json | 2 +- .../program_wise_fee_collection.js | 22 ++++ .../program_wise_fee_collection.json | 4 +- .../program_wise_fee_collection.py | 124 ++++++++++++++++++ 5 files changed, 156 insertions(+), 13 deletions(-) create mode 100644 erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.js create mode 100644 erpnext/education/report/program_wise_fee_collection/program_wise_fee_collection.py 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 index 62f453d29d..38c1b6d7f3 100644 --- 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 @@ -1,16 +1,17 @@ { "chart_name": "Program wise Fee Collection", "chart_type": "Report", - "creation": "2020-07-27 16:19:03.077317", + "creation": "2020-08-05 16:19:53.398335", + "custom_options": "", "docstatus": 0, "doctype": "Dashboard Chart", - "dynamic_filters_json": "{}", + "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-07-27 16:19:11.333532", + "modified": "2020-08-05 16:20:47.436847", "modified_by": "Administrator", "module": "Education", "name": "Program wise Fee Collection", @@ -21,11 +22,7 @@ "timeseries": 0, "timespan": "Last Year", "type": "Bar", - "use_report_chart": 0, - "x_field": "Program", - "y_axis": [ - { - "y_field": "Fees Collected" - } - ] + "use_report_chart": 1, + "x_field": "", + "y_axis": [] } \ No newline at end of file diff --git a/erpnext/education/education_dashboard/education/education.json b/erpnext/education/education_dashboard/education/education.json index 6d9f2de360..41d33758b9 100644 --- a/erpnext/education/education_dashboard/education/education.json +++ b/erpnext/education/education_dashboard/education/education.json @@ -54,7 +54,7 @@ "idx": 0, "is_default": 0, "is_standard": 1, - "modified": "2020-07-27 18:42:42.872547", + "modified": "2020-08-05 16:22:17.428101", "modified_by": "Administrator", "module": "Education", "name": "Education", 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 0000000000..72e8f12e9d --- /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 index 6b7a9754f1..ee5c0dec79 100644 --- 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 @@ -8,7 +8,7 @@ "idx": 0, "is_standard": "Yes", "json": "{}", - "modified": "2020-07-27 18:00:22.852723", + "modified": "2020-08-05 14:14:12.410515", "modified_by": "Administrator", "module": "Education", "name": "Program wise Fee Collection", @@ -17,7 +17,7 @@ "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": "Query Report", + "report_type": "Script Report", "roles": [ { "role": "Academics User" 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 0000000000..c145359129 --- /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' + } + From 0c818927a5c7d166199b30e404fc1d234a5b68ff Mon Sep 17 00:00:00 2001 From: Marica Date: Wed, 5 Aug 2020 16:47:41 +0530 Subject: [PATCH 38/74] fix: get_regional_address_details missing positional arg 'company' (#22915) --- erpnext/regional/india/taxes.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js index 4d36cff1e6..fbccc6b078 100644 --- a/erpnext/regional/india/taxes.js +++ b/erpnext/regional/india/taxes.js @@ -10,6 +10,8 @@ erpnext.setup_auto_gst_taxation = (doctype) => { 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 || '', From 5da067b6891b9e85da63dce8b8810f6838e572f5 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 5 Aug 2020 18:18:57 +0530 Subject: [PATCH 39/74] fix: condition for checking reference detail for Payment Entry --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 9df8655ccf..842c64fdbe 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -897,7 +897,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre total_amount = ref_doc.get("grand_total") exchange_rate = 1 outstanding_amount = ref_doc.get("outstanding_amount") - 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 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= 'outstanding_amount': doc.get('dunning_amount'), 'allocated_amount': doc.get('dunning_amount') }) - else: + else: pe.append("references", { 'reference_doctype': dt, 'reference_name': dn, From 1923ef052c560859eb2c6086cdca1b7e19ee06eb Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 5 Aug 2020 19:42:25 +0530 Subject: [PATCH 40/74] refactor: Format and sanitise user inputs to search queries. (#22913) * refactor: Sanitize whitelisted method inputs Co-authored-by: Prssanna Desai Co-authored-by: Shivam Mishra * refactor: Format and sanitize tax_account_query inputs Co-authored-by: Nabin Hait Co-authored-by: Prssanna Desai Co-authored-by: Shivam Mishra * refactor: Validate and sanitize search inputs via decorator Co-authored-by: Nabin Hait Co-authored-by: Prssanna Desai Co-authored-by: Shivam Mishra * style: Minor formatting fix * refactor: Validate and sanitize search inputs using decorator * fix: Typo * fix: Remove unwanted import statement * refactor: Repalce validate_and_sanitize_search_inputs() with validate_and_sanitize_search_inputs Co-authored-by: Prssanna Desai Co-authored-by: Shivam Mishra Co-authored-by: Prssanna Desai Co-authored-by: Shivam Mishra Co-authored-by: Nabin Hait --- erpnext/accounts/doctype/account/account.py | 2 + .../doctype/journal_entry/journal_entry.py | 32 +++++++-- .../doctype/payment_order/payment_order.py | 2 + .../pos_closing_entry/pos_closing_entry.py | 13 ++-- .../doctype/pos_profile/pos_profile.py | 1 + .../doctype/pricing_rule/pricing_rule.py | 12 ++-- .../bank_reconciliation.py | 3 + .../asset_maintenance/asset_maintenance.py | 1 + .../asset_maintenance_log.py | 1 + .../request_for_quotation.py | 1 + erpnext/controllers/queries.py | 72 ++++++++++++++----- .../program_enrollment/program_enrollment.py | 2 + .../doctype/student_group/student_group.py | 1 + .../healthcare_practitioner.py | 1 + .../inpatient_record/inpatient_record.py | 1 + .../department_approver.py | 1 + erpnext/manufacturing/doctype/bom/bom.py | 1 + .../doctype/work_order/work_order.py | 1 + .../bom_variance_report.py | 5 +- .../production_planning_report.py | 3 - .../employee_benefit_application.py | 1 + .../doctype/payroll_entry/payroll_entry.py | 1 + erpnext/projects/doctype/project/project.py | 1 + erpnext/projects/doctype/task/task.py | 1 + .../projects/doctype/timesheet/timesheet.py | 1 + erpnext/projects/utils.py | 1 + erpnext/selling/doctype/customer/customer.py | 2 + .../doctype/product_bundle/product_bundle.py | 1 + .../doctype/sales_order/sales_order.py | 1 + .../page/point_of_sale/point_of_sale.py | 13 ++-- .../setup/doctype/party_type/party_type.py | 1 + .../item_alternative/item_alternative.py | 1 + .../material_request/material_request.py | 2 + .../doctype/packing_slip/packing_slip.py | 1 + .../quality_inspection/quality_inspection.py | 2 + 35 files changed, 138 insertions(+), 48 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index c6de6410eb..164f120067 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -244,6 +244,8 @@ class Account(NestedSet): 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/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index cfdae936a4..dda17082a2 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -841,13 +841,33 @@ def get_opening_accounts(company): @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_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index 4702e58cef..e5880aa67a 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -27,6 +27,7 @@ class PaymentOrder(Document): 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 @@ def get_mop_query(doctype, txt, searchfield, start, page_len, filters): }) @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 8eb0a222a4..9899219bdc 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 @@ class POSClosingEntry(Document): 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 @@ class POSClosingEntry(Document): {"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 @@ def get_cashiers(doctype, txt, searchfield, start, page_len, filters): @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 @@ def make_closing_entry_from_opening(opening_entry): 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 8655b4bf3a..789b4c3bd9 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -105,6 +105,7 @@ def get_series(): 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 d90ae28e5a..cff7d5ba22 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -433,14 +433,14 @@ def make_pricing_rule(doctype, docname): 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/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py index 7df090bf62..ce6baa6846 100644 --- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py @@ -290,6 +290,7 @@ def get_matching_transactions_payments(description_matching): 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 @@ def payment_entry_query(doctype, txt, searchfield, start, page_len, filters): ) @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 @@ def journal_entry_query(doctype, txt, searchfield, start, page_len, filters): ) @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/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py index 1869a29c8d..60c528bcc4 100644 --- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py @@ -106,6 +106,7 @@ def update_maintenance_log(asset_maintenance, item_code, item_name, task): 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 f169f01616..148357f392 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 @@ class AssetMaintenanceLog(Document): 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/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 4b852300e5..b54a585b97 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 @@ def get_list_context(context=None): 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 31e34987be..babc5bdd79 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -12,6 +12,7 @@ from frappe.utils import unique # 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 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters): # 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 @@ def lead_query(doctype, txt, searchfield, start, page_len, filters): # 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 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters): # 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 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters): @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 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals 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 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals @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 @@ def bom(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, @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 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters): 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 @@ def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_doctype_wise_filters(filters): @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 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters): @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 @@ def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters) @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 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters): @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 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters): @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/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py index 7536172891..3e27670d05 100644 --- a/erpnext/education/doctype/program_enrollment/program_enrollment.py +++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py @@ -97,6 +97,7 @@ class ProgramEnrollment(Document): 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 @@ def get_program_courses(doctype, txt, searchfield, start, page_len, filters): }) @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_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py index 8b61c899bc..0260b80864 100644 --- a/erpnext/education/doctype/student_group/student_group.py +++ b/erpnext/education/doctype/student_group/student_group.py @@ -108,6 +108,7 @@ def get_program_enrollment(academic_year, academic_term=None, program=None, batc @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/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py index 3dc7c1ec39..5da5a0657c 100644 --- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py +++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py @@ -71,6 +71,7 @@ def validate_service_item(item, msg): 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 69356baad5..bc76970601 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -222,6 +222,7 @@ def patient_leave_service_unit(inpatient_record, check_out, leave_from): 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/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py index d4c118f802..afd54b8346 100644 --- a/erpnext/hr/doctype/department_approver/department_approver.py +++ b/erpnext/hr/doctype/department_approver/department_approver.py @@ -11,6 +11,7 @@ class DepartmentApprover(Document): 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/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 8062342cfc..c51f655a66 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -911,6 +911,7 @@ def get_bom_diff(bom1, bom2): 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 f962a1157b..b7d968e974 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -632,6 +632,7 @@ class WorkOrder(Document): 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 e3e440ebc6..dc424b7605 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 @@ def get_columns(filters): "width": 180 } ]) - + columns.extend([ { "label": _("Finished Good"), @@ -73,7 +73,7 @@ def get_columns(filters): ]) return columns - + def get_data(filters): cond = "1=1" @@ -95,6 +95,7 @@ def get_data(filters): 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 5ac3923187..ebc01c65af 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 @@ class ProductionPlanReport(object): "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/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py index d7d00e6480..ef844fbd3b 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 @@ def get_benefit_amount_based_on_pro_rata(sal_struct, component_max_benefit): 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 ad9b6d86c8..554484febb 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py @@ -540,6 +540,7 @@ def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progr 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/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 6350f86abb..5bbd29c4c4 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -239,6 +239,7 @@ def get_list_context(context=None): } @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 cf2fd26e57..fb84094ffe 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -193,6 +193,7 @@ def check_if_child_exists(name): @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 7fe22bec4b..9e807f728e 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -214,6 +214,7 @@ def get_projectwise_timesheet_data(project, parent=None): 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 d0d88ebdf0..c39f908e43 100644 --- a/erpnext/projects/utils.py +++ b/erpnext/projects/utils.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals 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/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index e614acdb82..ca62488a8c 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -340,6 +340,7 @@ def get_loyalty_programs(doc): 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 @@ def make_address(args, is_primary_address=1): 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/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index 0c85a1b53c..d3281f733f 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -29,6 +29,7 @@ class ProductBundle(Document): 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.py b/erpnext/selling/doctype/sales_order/sales_order.py index ffb66354fa..f88289871e 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -888,6 +888,7 @@ def make_purchase_order(source_name, for_supplier=None, selected_items=[], targe @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 f7b7ed8b89..9f8410f40b 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -160,6 +160,7 @@ def get_item_group_condition(pos_profile): 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 +180,12 @@ def item_group_query(doctype, txt, searchfield, start, page_len, filters): @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 +230,7 @@ def get_past_order_list(search_term, status, limit=20): invoice_list = frappe.db.get_all('POS Invoice', filters={ 'status': status }, fields=fields) - + return invoice_list @frappe.whitelist() @@ -244,7 +245,7 @@ def set_customer_info(fieldname, customer, value=""): 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/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py index b29c305ee7..96e60936a4 100644 --- a/erpnext/setup/doctype/party_type/party_type.py +++ b/erpnext/setup/doctype/party_type/party_type.py @@ -10,6 +10,7 @@ class PartyType(Document): 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/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py index 522dfc67a9..190cb62e99 100644 --- a/erpnext/stock/doctype/item_alternative/item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/item_alternative.py @@ -43,6 +43,7 @@ class ItemAlternative(Document): 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 25f1ed9505..335175f21d 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -370,6 +370,7 @@ def get_items_based_on_default_supplier(supplier): 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 @@ def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, pa 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 4f831d7a85..a7a29cca7f 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -176,6 +176,7 @@ class PackingSlip(Document): 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 568e742876..c3bb514184 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -59,6 +59,7 @@ class QualityInspection(Document): (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 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): {'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, From 085061fa213ef0c942867044ab5d4dbe58482633 Mon Sep 17 00:00:00 2001 From: Afshan <33727827+AfshanKhan@users.noreply.github.com> Date: Thu, 6 Aug 2020 14:36:34 +0530 Subject: [PATCH 41/74] =?UTF-8?q?fix:=20show=20or=20hide=20section=20or=20?= =?UTF-8?q?attributes=20depending=20on=20other=20attributes=E2=80=A6=20(#2?= =?UTF-8?q?2861)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: show or hide section or attributes depending on other attributes for better UI * Update erpnext/stock/doctype/item/item.js Co-authored-by: Marica * fix: made has_variants checkbox to read_only if stock_exists Co-authored-by: Marica --- erpnext/stock/doctype/item/item.js | 2 +- erpnext/stock/doctype/item/item.json | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 735f35f36f..38e5fe53a7 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -117,7 +117,7 @@ frappe.ui.form.on("Item", { 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 963c87a0af..45526a3910 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", From 33a5fdfb78316dc91b7c440af38914f1b05a4322 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 6 Aug 2020 16:47:43 +0530 Subject: [PATCH 42/74] fix: unbound error in product configurator --- erpnext/portal/product_configurator/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py index f8af30a1c3..9eef16bed3 100644 --- a/erpnext/portal/product_configurator/utils.py +++ b/erpnext/portal/product_configurator/utils.py @@ -239,7 +239,8 @@ def get_next_attribute_and_values(item_code, selected_attributes): 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: From 01f664a88f1dfd666f99df66dbd0d5682877aee5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 6 Aug 2020 17:08:14 +0530 Subject: [PATCH 43/74] fix: handle product_info null --- erpnext/templates/generators/item/item_configure.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/erpnext/templates/generators/item/item_configure.js b/erpnext/templates/generators/item/item_configure.js index 163c955c56..284eb25218 100644 --- a/erpnext/templates/generators/item/item_configure.js +++ b/erpnext/templates/generators/item/item_configure.js @@ -194,9 +194,16 @@ class ItemConfigure { 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 = `${__('Add to cart')}`; - const product_action = in_stock ? add_to_cart : `${__('Not in Stock')}`; + var in_stock; + var add_to_cart; + var product_action; + if (product_info) { + in_stock = product_info.allow_items_not_in_stock ? 1 : product_info.in_stock; + add_to_cart = `${__('Add to cart')}`; + product_action = in_stock ? add_to_cart : `${__('Not in Stock')}`; + } else { + product_info = ''; + } const item_add_to_cart = one_item ? `