diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 9bb3fe4144..06724b1cfc 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -10,6 +10,7 @@ from erpnext.accounts.utils import get_balance_on, get_account_currency from erpnext.setup.utils import get_company_currency from erpnext.accounts.party import get_party_account from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount +from erpnext.hr.doctype.employee_loan.employee_loan import update_disbursement_status class JournalEntry(AccountsController): def __init__(self, arg1, arg2=None): @@ -46,6 +47,7 @@ class JournalEntry(AccountsController): self.make_gl_entries() self.update_advance_paid() self.update_expense_claim() + self.update_employee_loan() def get_title(self): return self.pay_to_recd_from or self.accounts[0].account @@ -69,6 +71,7 @@ class JournalEntry(AccountsController): self.make_gl_entries(1) self.update_advance_paid() self.update_expense_claim() + self.update_employee_loan() self.unlink_advance_entry_reference() def unlink_advance_entry_reference(self): @@ -503,6 +506,12 @@ class JournalEntry(AccountsController): doc = frappe.get_doc("Expense Claim", d.reference_name) update_reimbursed_amount(doc) + def update_employee_loan(self): + for d in self.accounts: + if d.reference_type=="Employee Loan" and flt(d.debit) > 0: + doc = frappe.get_doc("Employee Loan", d.reference_name) + update_disbursement_status(doc) + def validate_expense_claim(self): for d in self.accounts: if d.reference_type=="Expense Claim": diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 0bd6f86c26..54af579adb 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -8,6 +8,7 @@ "custom": 0, "docstatus": 0, "doctype": "DocType", + "document_type": "Document", "editable_grid": 1, "engine": "InnoDB", "fields": [ @@ -596,7 +597,7 @@ "label": "Reference Type", "length": 0, "no_copy": 0, - "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset", + "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nEmployee Loan", "permlevel": 0, "precision": "", "print_hide": 0, @@ -768,7 +769,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-17 16:28:35.118357", + "modified": "2017-03-02 05:02:10.102039", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.js b/erpnext/hr/doctype/employee_loan/employee_loan.js index cb9216f741..2f87acf6e8 100644 --- a/erpnext/hr/doctype/employee_loan/employee_loan.js +++ b/erpnext/hr/doctype/employee_loan/employee_loan.js @@ -36,7 +36,34 @@ frappe.ui.form.on('Employee Loan', { }) }, - mode_of_payment: function(frm){ + refresh: function(frm) { + if (frm.doc.docstatus == 1 && (frm.doc.status == "Sanctioned" || frm.doc.status == "Partially Disbursed")) { + frm.add_custom_button(__('Make Disbursement Entry'), function() { + frm.trigger("make_jv"); + }) + } + frm.trigger("toggle_fields"); + }, + + make_jv: function(frm) { + frappe.call({ + args: { + "employee_loan": frm.doc.name, + "company": frm.doc.company, + "employee_loan_account": frm.doc.employee_loan_account, + "employee": frm.doc.employee, + "loan_amount": frm.doc.loan_amount, + "payment_account": frm.doc.payment_account + }, + method: "erpnext.hr.doctype.employee_loan.employee_loan.make_jv_entry", + callback: function(r) { + if (r.message) + var doc = frappe.model.sync(r.message)[0]; + frappe.set_route("Form", doc.doctype, doc.name); + } + }) + }, + mode_of_payment: function(frm) { frappe.call({ method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account", args: { @@ -51,23 +78,6 @@ frappe.ui.form.on('Employee Loan', { }); }, - refresh: function(frm) { - frm.trigger("toggle_fields"); - - if(frm.doc.docstatus==1) { - 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, - group_by_voucher: 0 - }; - frappe.set_route("query-report", "General Ledger"); - }, "fa fa-table"); - } - }, - employee_loan_application: function(frm) { return frm.call({ method: "erpnext.hr.doctype.employee_loan.employee_loan.get_employee_loan_application", diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.json b/erpnext/hr/doctype/employee_loan/employee_loan.json index c052dc028b..a14c1e0c5f 100644 --- a/erpnext/hr/doctype/employee_loan/employee_loan.json +++ b/erpnext/hr/doctype/employee_loan/employee_loan.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, "autoname": "ELN.####", @@ -237,7 +238,7 @@ "label": "Status", "length": 0, "no_copy": 0, - "options": "Loan Unpaid\nLoan Paid\nEMI in progress\nLoan Repaid", + "options": "Sanctioned\nPartially Disbursed\nFully Disbursed\nRepaid/Closed", "permlevel": 0, "precision": "", "print_hide": 0, @@ -325,6 +326,7 @@ "label": "Loan Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -506,6 +508,7 @@ "label": "Monthly Repayment Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -690,7 +693,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, "set_only_once": 0, "unique": 0 @@ -801,6 +804,7 @@ "label": "Total Payment", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -859,6 +863,7 @@ "label": "Total Interest Payable", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -901,17 +906,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 1, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-22 04:27:13.174800", + "modified": "2017-03-09 01:30:19.231918", "modified_by": "Administrator", "module": "HR", "name": "Employee Loan", diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.py b/erpnext/hr/doctype/employee_loan/employee_loan.py index 568596ee25..d4e9a20b49 100644 --- a/erpnext/hr/doctype/employee_loan/employee_loan.py +++ b/erpnext/hr/doctype/employee_loan/employee_loan.py @@ -8,7 +8,6 @@ import erpnext from frappe import _ from frappe.utils import flt, rounded, add_months, nowdate from erpnext.controllers.accounts_controller import AccountsController -from erpnext.accounts.general_ledger import make_gl_entries class EmployeeLoan(AccountsController): def validate(self): @@ -26,33 +25,32 @@ class EmployeeLoan(AccountsController): self.set_repayment_period() self.calculate_totals() - def on_submit(self): - self.make_gl_entries() + def make_jv_entry(self): + self.check_permission('write') + journal_entry = frappe.new_doc('Journal Entry') + journal_entry.voucher_type = 'Bank Entry' + journal_entry.user_remark = _('Against Employee Loan: {0}').format(self.name) + journal_entry.company = self.company + journal_entry.posting_date = nowdate() - def on_cancel(self): - self.make_gl_entries() + account_amt_list = [] - def make_gl_entries(self): - gl_entries = [] - # Gl entries for employee loan account - gl_entries.append( - self.get_gl_dict({ - "account": self.employee_loan_account, - "party_type": "Employee", - "party": self.employee, - "debit": self.loan_amount, - "debit_in_account_currency": self.loan_amount + account_amt_list.append({ + "account": self.employee_loan_account, + "party_type": "Employee", + "party": self.employee, + "debit_in_account_currency": self.loan_amount, + "reference_type": "Employee Loan", + "reference_name": self.name, }) - ) - # Gl entries for payment account - gl_entries.append( - self.get_gl_dict({ - "account": self.payment_account, - "credit": self.loan_amount, - "credit_in_account_currency": self.loan_amount + account_amt_list.append({ + "account": self.payment_account, + "credit_in_account_currency": self.loan_amount, + "reference_type": "Employee Loan", + "reference_name": self.name, }) - ) - make_gl_entries(gl_entries, cancel=(self.docstatus == 2)) + journal_entry.set("accounts", account_amt_list) + return journal_entry.as_dict() def make_repayment_schedule(self): self.repayment_schedule = [] @@ -94,11 +92,19 @@ class EmployeeLoan(AccountsController): self.total_payment += data.total_payment self.total_interest_payable +=data.interest_amount - def update_status(self): - if self.disbursement_date: - self.status = "Loan Paid" - if len(self.repayment_schedule)>0: - self.status = "repayment in progress" + +def update_disbursement_status(doc): + disbursed_amount = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) as disbursed_amount + from `tabGL Entry` where against_voucher_type = 'Employee Loan' and against_voucher = %s""", + (doc.name), as_dict=1)[0].disbursed_amount + if disbursed_amount == doc.loan_amount: + frappe.db.set_value("Employee Loan", doc.name , "status", "Fully Disbursed") + if disbursed_amount < doc.loan_amount and disbursed_amount != 0: + frappe.db.set_value("Employee Loan", doc.name , "status", "Partially Disbursed") + if disbursed_amount == 0: + frappe.db.set_value("Employee Loan", doc.name , "status", "Sanctioned") + if disbursed_amount > doc.loan_amount: + frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount)) def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods): if repayment_method == "Repay Over Number of Periods" and not repayment_periods: @@ -124,4 +130,29 @@ def get_monthly_repayment_amount(repayment_method, loan_amount, rate_of_interest def get_employee_loan_application(employee_loan_application): employee_loan = frappe.get_doc("Employee Loan Application", employee_loan_application) if employee_loan: - return employee_loan \ No newline at end of file + return employee_loan + +@frappe.whitelist() +def make_jv_entry(employee_loan, company, employee_loan_account, employee, loan_amount, payment_account): + journal_entry = frappe.new_doc('Journal Entry') + journal_entry.voucher_type = 'Bank Entry' + journal_entry.user_remark = _('Against Employee Loan: {0}').format(employee_loan) + journal_entry.company = company + journal_entry.posting_date = nowdate() + + account_amt_list = [] + + account_amt_list.append({ + "account": employee_loan_account, + "debit_in_account_currency": loan_amount, + "reference_type": "Employee Loan", + "reference_name": employee_loan, + }) + account_amt_list.append({ + "account": payment_account, + "credit_in_account_currency": loan_amount, + "reference_type": "Employee Loan", + "reference_name": employee_loan, + }) + journal_entry.set("accounts", account_amt_list) + return journal_entry.as_dict() \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_loan/test_employee_loan.py b/erpnext/hr/doctype/employee_loan/test_employee_loan.py index c1c6ba24a9..8671baae4f 100644 --- a/erpnext/hr/doctype/employee_loan/test_employee_loan.py +++ b/erpnext/hr/doctype/employee_loan/test_employee_loan.py @@ -60,7 +60,8 @@ def create_employee_loan(employee, loan_type, loan_amount, repayment_method, rep "disbursement_date": nowdate(), "mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'), "payment_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name"), - "employee_loan_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name") + "employee_loan_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name"), + "interest_income_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name") }) employee_loan.insert() return employee_loan diff --git a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json index 29617dd059..4c673c385e 100644 --- a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json +++ b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json @@ -266,6 +266,7 @@ "label": "Loan Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -470,6 +471,7 @@ "label": "Total Payable Interest", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -528,6 +530,7 @@ "label": "Monthly Repayment Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -587,6 +590,7 @@ "label": "Total Payable Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -639,7 +643,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-27 04:52:39.344524", + "modified": "2017-03-02 04:25:43.397934", "modified_by": "Administrator", "module": "HR", "name": "Employee Loan Application", diff --git a/erpnext/hr/doctype/loan_type/loan_type.json b/erpnext/hr/doctype/loan_type/loan_type.json index 3809fc1547..ce9397923d 100644 --- a/erpnext/hr/doctype/loan_type/loan_type.json +++ b/erpnext/hr/doctype/loan_type/loan_type.json @@ -58,6 +58,7 @@ "label": "Maximum Loan Amount", "length": 0, "no_copy": 0, + "options": "Company:company:default_currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -198,7 +199,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-27 04:53:51.949600", + "modified": "2017-03-02 04:26:05.375693", "modified_by": "Administrator", "module": "HR", "name": "Loan Type",