From 4e0559bc7948fc175e81e0e2752caa5157b39851 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Tue, 25 Jul 2017 15:22:47 +0530 Subject: [PATCH] make payment entry for the fees --- .../doctype/payment_entry/payment_entry.js | 28 +- .../doctype/payment_entry/payment_entry.py | 47 ++-- .../payment_request/payment_request.py | 3 - .../doctype/sales_invoice/sales_invoice.py | 8 - erpnext/accounts/general_ledger.py | 1 - erpnext/schools/api.py | 7 + .../doctype/fee_request/fee_request.js | 2 +- .../doctype/fee_request/fee_request.py | 3 - .../doctype/fee_request/test_fee_request.py | 1 - .../fee_request_program.py | 1 - .../fee_request_student_group.py | 1 - .../doctype/fee_structure/fee_structure.js | 21 ++ .../doctype/fee_structure/fee_structure.json | 250 +++++++++++++++--- erpnext/schools/doctype/fees/fees.js | 85 +++--- erpnext/schools/doctype/fees/fees.json | 12 +- erpnext/schools/doctype/fees/fees.py | 87 +++++- erpnext/schools/doctype/fees/fees_list.js | 17 +- erpnext/schools/doctype/student/student.json | 2 +- 18 files changed, 436 insertions(+), 140 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index d1318d0b518..9bc649f774f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -12,7 +12,8 @@ frappe.ui.form.on('Payment Entry', { setup: function(frm) { frm.set_query("paid_from", function() { - var party_account_type = frm.doc.party_type=="Customer" ? "Receivable" : "Payable"; + var party_account_type = in_list(["Customer", "Student"], frm.doc.party_type) ? + "Receivable" : "Payable"; var account_types = in_list(["Pay", "Internal Transfer"], frm.doc.payment_type) ? ["Bank", "Cash"] : party_account_type; @@ -28,13 +29,14 @@ frappe.ui.form.on('Payment Entry', { frm.set_query("party_type", function() { return{ "filters": { - "name": ["in",["Customer","Supplier", "Employee"]], + "name": ["in",["Customer","Supplier", "Employee", "Student"]], } } }); frm.set_query("paid_to", function() { - var party_account_type = frm.doc.party_type=="Customer" ? "Receivable" : "Payable"; + var party_account_type = in_list(["Customer", "Student"], frm.doc.party_type) ? + "Receivable" : "Payable"; var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ? ["Bank", "Cash"] : party_account_type; @@ -72,6 +74,8 @@ frappe.ui.form.on('Payment Entry', { var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"]; } else if (frm.doc.party_type=="Employee") { var doctypes = ["Expense Claim", "Journal Entry"]; + } else if (frm.doc.party_type=="Student") { + var doctypes = ["Fees"]; } else { var doctypes = ["Journal Entry"]; } @@ -85,7 +89,7 @@ frappe.ui.form.on('Payment Entry', { child = locals[cdt][cdn]; filters = {"docstatus": 1, "company": doc.company}; party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice', - 'Purchase Order', 'Expense Claim']; + 'Purchase Order', 'Expense Claim', 'Fees']; if (in_list(party_type_doctypes, child.reference_doctype)) { filters[doc.party_type.toLowerCase()] = doc.party; @@ -207,19 +211,13 @@ frappe.ui.form.on('Payment Entry', { frm.set_value(field, null); }); } else { - if(!frm.doc.party) - { - if (frm.doc.payment_type=="Receive"){ - frm.set_value("party_type", "Customer"); - } - } - else - { - frm.events.party(frm); + if(frm.doc.party) { + frm.events.party(frm); } - if(frm.doc.mode_of_payment) + if(frm.doc.mode_of_payment) { frm.events.mode_of_payment(frm); + } } }, @@ -254,6 +252,7 @@ frappe.ui.form.on('Payment Entry', { date: frm.doc.posting_date }, callback: function(r, rt) { + console.log(r, rt); if(r.message) { if(frm.doc.payment_type == "Receive") { frm.set_value("paid_from", r.message.party_account); @@ -491,6 +490,7 @@ frappe.ui.form.on('Payment Entry', { } }, callback: function(r, rt) { + console.log(r, rt); if(r.message) { var total_positive_outstanding = 0; var total_negative_outstanding = 0; diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 29ad83152d0..bf2213ec46c 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -103,6 +103,9 @@ class PaymentEntry(AccountsController): self.party_name = frappe.db.get_value(self.party_type, self.party, self.party_type.lower() + "_name") + _party_name = "title" if self.party_type == "Student" else self.party_type.lower() + "_name" + self.party_name = frappe.db.get_value(self.party_type, self.party, _party_name) + if self.party: if not self.party_balance: self.party_balance = get_balance_on(party_type=self.party_type, @@ -149,7 +152,7 @@ class PaymentEntry(AccountsController): frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party)) if self.party_account: - party_account_type = "Receivable" if self.party_type=="Customer" else "Payable" + party_account_type = "Receivable" if self.party_type in ("Customer", "Student") else "Payable" self.validate_account_type(self.party_account, [party_account_type]) def validate_bank_accounts(self): @@ -182,7 +185,9 @@ class PaymentEntry(AccountsController): frappe.throw(_("{0} is mandatory").format(self.meta.get_label(field))) def validate_reference_documents(self): - if self.party_type == "Customer": + if self.party_type == "Student": + valid_reference_doctypes = ("Fees") + elif self.party_type == "Customer": valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry") elif self.party_type == "Supplier": valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry") @@ -209,13 +214,17 @@ class PaymentEntry(AccountsController): else: self.validate_journal_entry() - if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim"): - if self.party_type=="Customer": + if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim", "Fees"): + if self.party_type in ("Customer", "Student"): ref_party_account = ref_doc.debit_to elif self.party_type=="Supplier": ref_party_account = ref_doc.credit_to elif self.party_type=="Employee": ref_party_account = ref_doc.payable_account + + if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Fees"): + ref_party_account = ref_doc.debit_to \ + if self.party_type in ("Customer", "Student") else ref_doc.credit_to if ref_party_account != self.party_account: frappe.throw(_("{0} {1} is associated with {2}, but Party Account is {3}") @@ -397,9 +406,9 @@ class PaymentEntry(AccountsController): "against": against_account, "account_currency": self.party_account_currency }) - - dr_or_cr = "credit" if self.party_type == "Customer" else "debit" - + + dr_or_cr = "credit" if self.party_type in ["Customer", "Student"] else "debit" + for d in self.get("references"): gle = party_gl_dict.copy() gle.update({ @@ -498,11 +507,13 @@ def get_outstanding_reference_documents(args): # Get negative outstanding sales /purchase invoices total_field = "base_grand_total" if party_account_currency == company_currency else "grand_total" - negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"), - args.get("party"), args.get("party_account"), total_field) + negative_outstanding_invoices = [] + if (args.get("party_type") != "Student"): + negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"), + args.get("party"), args.get("party_account"), total_field) - # Get positive outstanding sales /purchase invoices - outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"), + # Get positive outstanding sales /purchase invoices/ Fees + outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"), args.get("party_account")) for d in outstanding_invoices: @@ -518,9 +529,11 @@ def get_outstanding_reference_documents(args): d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no") # Get all SO / PO which are not fully billed or aginst which full advance not paid - orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"), - party_account_currency, company_currency) - + orders_to_be_billed = [] + if (args.get("party_type") != "Student"): + orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), + args.get("party"), party_account_currency, company_currency) + return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency): @@ -634,7 +647,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre total_amount = outstanding_amount = exchange_rate = None ref_doc = frappe.get_doc(reference_doctype, reference_name) - if reference_doctype != "Journal Entry": + if reference_doctype == "Fees": + total_amount = ref_doc.get("grand_total") + exchange_rate = 1 + outstanding_amount = ref_doc.get("outstanding_amount") + elif reference_doctype != "Journal Entry": if party_account_currency == ref_doc.company_currency: if ref_doc.doctype == "Expense Claim": total_amount = ref_doc.total_sanctioned_amount diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 3796877293e..807ad280dbe 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -61,7 +61,6 @@ class PaymentRequest(Document): def set_payment_request_url(self): if self.payment_account: self.payment_url = self.get_payment_url() - print (self.payment_url) if self.payment_url: self.db_set('payment_url', self.payment_url) @@ -102,7 +101,6 @@ class PaymentRequest(Document): def create_payment_entry(self, submit=True): """create entry""" - print ("creating the payment entry") frappe.flags.ignore_account_permission = True ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) @@ -257,7 +255,6 @@ def make_payment_request(**args): if args.order_type == "Shopping Cart" or args.mute_email: pr.flags.mute_email = True - print ("comign in creatinf the new dottype") if args.submit_doc: pr.insert(ignore_permissions=True) pr.submit() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 800ec1460d1..7a787c4cba3 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -583,11 +583,8 @@ class SalesInvoice(SellingController): return if not gl_entries: - print ("if not gl_entries") gl_entries = self.get_gl_entries() - print (gl_entries) - if gl_entries: from erpnext.accounts.general_ledger import make_gl_entries @@ -596,7 +593,6 @@ class SalesInvoice(SellingController): make_gl_entries(gl_entries, cancel=(self.docstatus == 2), update_outstanding=update_outstanding, merge_entries=False) - # frappe.throw("go ahead bro") if update_outstanding == "No": from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt @@ -613,22 +609,18 @@ class SalesInvoice(SellingController): delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) def get_gl_entries(self, warehouse_account=None): - print ("inside the get_gl_entries") from erpnext.accounts.general_ledger import merge_similar_entries gl_entries = [] self.make_customer_gl_entry(gl_entries) - print ("make cuustomer gl entry", gl_entries) self.make_tax_gl_entries(gl_entries) self.make_item_gl_entries(gl_entries) - print ("make item gl entry", gl_entries) # merge gl entries before adding pos entries gl_entries = merge_similar_entries(gl_entries) - print ("after merged gl entry", gl_entries) self.make_pos_gl_entries(gl_entries) self.make_gle_for_change_amount(gl_entries) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 23715fa457c..c575d59ae74 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -116,7 +116,6 @@ def round_off_debit_credit(gl_map): currency=frappe.db.get_value("Company", gl_map[0].company, "default_currency", cache=True)) debit_credit_diff = 0.0 - print ("gl map", gl_map) for entry in gl_map: entry.debit = flt(entry.debit, precision) entry.credit = flt(entry.credit, precision) diff --git a/erpnext/schools/api.py b/erpnext/schools/api.py index 41d4a0dcb88..13aa74bc226 100644 --- a/erpnext/schools/api.py +++ b/erpnext/schools/api.py @@ -354,3 +354,10 @@ def update_email_group(doctype, name): if email: email_list.append(email) add_subscribers(name, email_list) + +@frappe.whitelist() +def get_current_enrollment(student, academic_year=None): + current_academic_year = academic_year or frappe.defaults.get_defaults().academic_year + return frappe.get_all("Program Enrollment", fields=["name", "student", "student_name", "student_category", + "program", "student_batch_name", "academic_year", "academic_term"], filters={"student":student, + "academic_year": current_academic_year})[0] diff --git a/erpnext/schools/doctype/fee_request/fee_request.js b/erpnext/schools/doctype/fee_request/fee_request.js index 30f8e5bfaac..830940e1954 100644 --- a/erpnext/schools/doctype/fee_request/fee_request.js +++ b/erpnext/schools/doctype/fee_request/fee_request.js @@ -3,7 +3,7 @@ frappe.ui.form.on('Fee Request', { refresh: function(frm) { - frm.disable_save(); + frm.disable_save(); }, fee_structure: function(frm) { if (frm.doc.fee_structure) { diff --git a/erpnext/schools/doctype/fee_request/fee_request.py b/erpnext/schools/doctype/fee_request/fee_request.py index a3552b9b7d2..f8cb554f96f 100644 --- a/erpnext/schools/doctype/fee_request/fee_request.py +++ b/erpnext/schools/doctype/fee_request/fee_request.py @@ -7,9 +7,6 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc -from erpnext.schools.api import get_student_group_students -from erpnext.schools.doctype.student_group.student_group import get_program_enrollment -from frappe.model.mapper import get_mapped_doc from frappe.utils import money_in_words diff --git a/erpnext/schools/doctype/fee_request/test_fee_request.py b/erpnext/schools/doctype/fee_request/test_fee_request.py index a76ea30de60..f419e942e70 100644 --- a/erpnext/schools/doctype/fee_request/test_fee_request.py +++ b/erpnext/schools/doctype/fee_request/test_fee_request.py @@ -3,7 +3,6 @@ # See license.txt from __future__ import unicode_literals -import frappe import unittest class TestFeeRequest(unittest.TestCase): diff --git a/erpnext/schools/doctype/fee_request_program/fee_request_program.py b/erpnext/schools/doctype/fee_request_program/fee_request_program.py index a4473b90f8e..61ce1d5782d 100644 --- a/erpnext/schools/doctype/fee_request_program/fee_request_program.py +++ b/erpnext/schools/doctype/fee_request_program/fee_request_program.py @@ -3,7 +3,6 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document class FeeRequestProgram(Document): diff --git a/erpnext/schools/doctype/fee_request_student_group/fee_request_student_group.py b/erpnext/schools/doctype/fee_request_student_group/fee_request_student_group.py index ecbc3abd382..777d225d9a8 100644 --- a/erpnext/schools/doctype/fee_request_student_group/fee_request_student_group.py +++ b/erpnext/schools/doctype/fee_request_student_group/fee_request_student_group.py @@ -3,7 +3,6 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document class FeeRequestStudentGroup(Document): diff --git a/erpnext/schools/doctype/fee_structure/fee_structure.js b/erpnext/schools/doctype/fee_structure/fee_structure.js index fa46278859f..7619cf5fbcd 100644 --- a/erpnext/schools/doctype/fee_structure/fee_structure.js +++ b/erpnext/schools/doctype/fee_structure/fee_structure.js @@ -1,3 +1,24 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +cur_frm.add_fetch("company", "default_receivable_account", "debit_to"); +cur_frm.add_fetch("company", "default_income_account", "against_income_account"); +cur_frm.add_fetch("company", "cost_center", "cost_center"); + +frappe.ui.form.on('Fee Structure', { + onload: function(frm) { + frm.set_query("debit_to", function(doc) { + return { + filters: { + 'account_type': 'Receivable', + 'is_group': 0, + 'company': doc.company + } + }; + }); + } +}); + frappe.ui.form.on("Fee Component", { amount: function(frm) { var total_amount = 0; diff --git a/erpnext/schools/doctype/fee_structure/fee_structure.json b/erpnext/schools/doctype/fee_structure/fee_structure.json index f5b48dcbd72..c0daa33fb37 100644 --- a/erpnext/schools/doctype/fee_structure/fee_structure.json +++ b/erpnext/schools/doctype/fee_structure/fee_structure.json @@ -44,6 +44,37 @@ "set_only_once": 1, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "student_category", + "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 Category", + "length": 0, + "no_copy": 0, + "options": "Student Category", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -77,37 +108,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "student_category", - "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 Category", - "length": 0, - "no_copy": 0, - "options": "Student Category", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -380,6 +380,190 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "accounts", + "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": "Accounts", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "fieldname": "debit_to", + "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": "Debit To", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "against_income_account", + "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": "Credit To", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_16", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cost_center", + "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": "Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Company", + "length": 0, + "no_copy": 0, + "options": "Company", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 } ], "has_web_view": 0, @@ -394,8 +578,8 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-18 15:02:29.909472", - "modified_by": "Administrator", + "modified": "2017-07-27 12:52:12.439685", + "modified_by": "manas@erpnext.com", "module": "Schools", "name": "Fee Structure", "name_case": "", diff --git a/erpnext/schools/doctype/fees/fees.js b/erpnext/schools/doctype/fees/fees.js index d5e71fe9ec7..20cb5bc60f7 100644 --- a/erpnext/schools/doctype/fees/fees.js +++ b/erpnext/schools/doctype/fees/fees.js @@ -1,5 +1,11 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt cur_frm.add_fetch("student", "title", "student_name"); +cur_frm.add_fetch("student", "student_email_id", "student_email"); +cur_frm.add_fetch("company", "default_receivable_account", "debit_to"); +cur_frm.add_fetch("company", "default_income_account", "against_income_account"); +cur_frm.add_fetch("company", "cost_center", "cost_center"); frappe.ui.form.on("Fees", { onload: function(frm){ @@ -19,7 +25,7 @@ frappe.ui.form.on("Fees", { }; }); - // debit account for booking the fee + // debit account for booking the fee frm.set_query("debit_to", function(doc) { return { filters: { @@ -27,11 +33,11 @@ frappe.ui.form.on("Fees", { 'is_group': 0, 'company': doc.company } - } + }; }); if (!frm.doc.posting_date) { - frm.doc.posting_date = frappe.datetime.get_today() + frm.doc.posting_date = frappe.datetime.get_today(); } }, @@ -57,56 +63,75 @@ frappe.ui.form.on("Fees", { } if(frm.doc.docstatus===1 && frm.doc.outstanding_amount>0) { frm.add_custom_button(__("Payment Request"), function() { - frm.events.make_payment_request(frm) + frm.events.make_payment_request(frm); }, __("Make")); frm.page.set_inner_btn_group_as_primary(__("Make")); } if(frm.doc.docstatus===1 && frm.doc.outstanding_amount!=0) { frm.add_custom_button(__("Payment"), function() { - frm.events.make_payment_entry(frm) + frm.events.make_payment_entry(frm); }, __("Make")); frm.page.set_inner_btn_group_as_primary(__("Make")); } }, - // if (frm.doc.docstatus === 1 && (frm.doc.total_amount > frm.doc.paid_amount)) { - // frm.add_custom_button(__("Collect Fees"), function() { - // frappe.prompt({fieldtype:"Float", label: __("Amount Paid"), fieldname:"amt"}, - // function(data) { - // frappe.call({ - // method:"erpnext.schools.api.collect_fees", - // args: { - // "fees": frm.doc.name, - // "amt": data.amt - // }, - // callback: function(r) { - // frm.doc.paid_amount = r.message - // frm.doc.outstanding_amount = frm.doc.total_amount - r.message - // frm.refresh() - // } - // }); - // }, __("Enter Paid Amount"), __("Collect")); - // }); - // } + + student: function(frm) { + if (frm.doc.student) { + frappe.call({ + method:"erpnext.schools.api.get_current_enrollment", + args: { + "student": frm.doc.student, + "academic_year": frm.doc.academic_year + }, + callback: function(r) { + if(r){ + console.log(r); + frm.set_value("student_name", r.message.student_name); + frm.set_value("program_enrollment", r.message.name); + frm.set_value("program", r.message.program); + frm.set_value("student_batch", r.message.student_batch_name); + frm.set_value("student_category", r.message.student_category); + frm.set_value("academic_term", r.message.academic_term); + frm.set_value("academic_year", r.message.academic_year); + } + } + }); + } + }, make_payment_request: function(frm) { frappe.call({ method:"erpnext.accounts.doctype.payment_request.payment_request.make_payment_request", args: { - "dt": cur_frm.doc.doctype, - "dn": cur_frm.doc.name, - "recipient_id": cur_frm.doc.contact_email + "dt": frm.doc.doctype, + "dn": frm.doc.name, + "recipient_id": frm.doc.contact_email }, callback: function(r) { if(!r.exc){ var doc = frappe.model.sync(r.message); - frappe.set_route("Form", r.message.doctype, r.message.name); + frappe.set_route("Form", doc[0].doctype, doc[0].name); } } - }) + }); + }, + + make_payment_entry: function(frm) { + return frappe.call({ + method: "erpnext.schools.doctype.fees.fees.get_payment_entry", + args: { + "dt": frm.doc.doctype, + "dn": frm.doc.name + }, + callback: function(r) { + var doc = frappe.model.sync(r.message); + frappe.set_route("Form", doc[0].doctype, doc[0].name); + } + }); }, set_posting_time: function(frm) { - frm.refresh() + frm.refresh(); }, program: function(frm) { diff --git a/erpnext/schools/doctype/fees/fees.json b/erpnext/schools/doctype/fees/fees.json index 1a9dcc0c6a6..28cc25ea5d8 100644 --- a/erpnext/schools/doctype/fees/fees.json +++ b/erpnext/schools/doctype/fees/fees.json @@ -477,9 +477,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "contact_email", + "fieldname": "student_email", "fieldtype": "Data", - "hidden": 1, + "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -904,7 +904,7 @@ "default": "0", "fieldname": "paid_amount", "fieldtype": "Currency", - "hidden": 0, + "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -1093,7 +1093,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Account", + "label": "Accounting", "length": 0, "no_copy": 0, "permlevel": 0, @@ -1242,8 +1242,8 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-24 20:01:58.683352", - "modified_by": "Administrator", + "modified": "2017-07-27 12:58:44.197451", + "modified_by": "manas@erpnext.com", "module": "Schools", "name": "Fees", "name_case": "", diff --git a/erpnext/schools/doctype/fees/fees.py b/erpnext/schools/doctype/fees/fees.py index 824a6647c2f..801319452e3 100644 --- a/erpnext/schools/doctype/fees/fees.py +++ b/erpnext/schools/doctype/fees/fees.py @@ -6,25 +6,28 @@ from __future__ import unicode_literals from frappe.model.document import Document import frappe from frappe import _ -from frappe.utils import money_in_words +from frappe.utils import money_in_words, nowdate from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request from frappe.utils.csvutils import getlink +from erpnext.accounts.utils import get_account_currency from erpnext.controllers.accounts_controller import AccountsController - +from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account class Fees(AccountsController): + def set_indicator(self): + """Set indicator for portal""" + if self.outstanding_amount > 0: + self.indicator_color = "orange" + self.indicator_title = _("Unpaid") + else: + self.indicator_color = "green" + self.indicator_title = _("Paid") + def validate(self): - self.set_missing_values() self.calculate_total() - # self.validate_debit_to_account() - - def set_missing_values(self): - if not self.contact_email: - self.contact_email = "manas@erpnext.com" - if not self.against_income_account: - self.against_income_account = "Academic Fees - S" - if not self.cost_center: - self.cost_center = "Main - S" + ''' + set missing field here and validate the accounts + ''' def calculate_total(self): """Calculates total amount.""" @@ -77,6 +80,66 @@ def get_fee_list(doctype, txt, filters, limit_start, limit_page_length=20, order order by due_date asc limit {0} , {1}''' .format(limit_start, limit_page_length), student, as_dict = True) + +@frappe.whitelist() +def get_payment_entry(dt, dn, bank_account=None): + doc = frappe.get_doc(dt, dn) + + party_type = "Student" + party_account = doc.debit_to + party_account_currency = doc.get("currency") or get_account_currency(party_account) + + # payment type + if (doc.outstanding_amount > 0): + payment_type = "Receive" + + # amounts + grand_total = outstanding_amount = 0 + grand_total = doc.grand_total + outstanding_amount = doc.outstanding_amount + + # bank or cash + bank = get_default_bank_cash_account(doc.company, "Bank") + + paid_amount = received_amount = 0 + if party_account_currency == bank.account_currency: + paid_amount = received_amount = abs(outstanding_amount) + elif payment_type == "Receive": + paid_amount = abs(outstanding_amount) + else: + received_amount = abs(outstanding_amount) + + pe = frappe.new_doc("Payment Entry") + pe.payment_type = payment_type + pe.company = doc.company + pe.posting_date = nowdate() + pe.mode_of_payment = doc.get("mode_of_payment") + pe.party_type = party_type + pe.party = doc.student + pe.party_name = doc.student_name + pe.paid_from = party_account if payment_type=="Receive" else bank.account + pe.paid_to = party_account if payment_type=="Pay" else bank.account + pe.paid_from_account_currency = party_account_currency if payment_type=="Receive" else bank.account_currency + pe.paid_to_account_currency = party_account_currency if payment_type=="Pay" else bank.account_currency + pe.paid_amount = paid_amount + pe.received_amount = received_amount + pe.allocate_payment_amount = 1 + pe.letter_head = doc.get("letter_head") + + pe.append("references", { + "reference_doctype": dt, + "reference_name": dn, + "due_date": doc.get("due_date"), + "total_amount": grand_total, + "outstanding_amount": outstanding_amount, + "allocated_amount": outstanding_amount + }) + + pe.setup_party_account_field() + pe.set_missing_values() + return pe + + def get_list_context(context=None): return { "show_sidebar": True, diff --git a/erpnext/schools/doctype/fees/fees_list.js b/erpnext/schools/doctype/fees/fees_list.js index 98314819d56..c7117f203c2 100644 --- a/erpnext/schools/doctype/fees/fees_list.js +++ b/erpnext/schools/doctype/fees/fees_list.js @@ -1,15 +1,12 @@ frappe.listview_settings['Fees'] = { - add_fields: [ "grand_total", "paid_amount", "due_date"], + add_fields: ["grand_total", "outstanding_amount", "due_date"], get_indicator: function(doc) { - var { get_today } = frappe.datetime; - if ((doc.grand_total > doc.paid_amount) && doc.due_date < get_today()) { - return [__("Overdue"), "red", ["due_date,<," + get_today()], ["due_date,<," + get_today()]]; - } - else if (doc.grand_total > doc.paid_amount) { - return [__("Pending"), "orange"]; - } - else { - return [__("Paid"), "green"]; + if(flt(doc.outstanding_amount)==0) { + return [__("Paid"), "green", "outstanding_amount,=,0"] + } else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) { + return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"] + } else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) { + return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"] } } }; \ No newline at end of file diff --git a/erpnext/schools/doctype/student/student.json b/erpnext/schools/doctype/student/student.json index 75cb758b069..4961c2db8a8 100644 --- a/erpnext/schools/doctype/student/student.json +++ b/erpnext/schools/doctype/student/student.json @@ -1114,7 +1114,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-07 16:30:08.930882", + "modified": "2017-07-26 19:46:26.893441", "modified_by": "Administrator", "module": "Schools", "name": "Student",