Merge branch 'develop' of github.com:frappe/erpnext into develop
This commit is contained in:
commit
d9a265fab1
@ -337,14 +337,19 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup
|
||||
|
||||
def validate_party_frozen_disabled(party_type, party_name):
|
||||
if party_type and party_name:
|
||||
if party_type in ("Customer", "Supplier"):
|
||||
party = frappe.db.get_value(party_type, party_name, ["is_frozen", "disabled"], as_dict=True)
|
||||
if party.disabled:
|
||||
frappe.throw(_("{0} {1} is disabled").format(party_type, party_name), PartyDisabled)
|
||||
elif party.is_frozen:
|
||||
elif party.get("is_frozen"):
|
||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||
if not frozen_accounts_modifier in frappe.get_roles():
|
||||
frappe.throw(_("{0} {1} is frozen").format(party_type, party_name), PartyFrozen)
|
||||
|
||||
elif party_type == "Employee":
|
||||
if frappe.db.get_value("Employee", party_name, "status") == "Left":
|
||||
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), PartyDisabled, alert=True)
|
||||
|
||||
def get_timeline_data(doctype, name):
|
||||
'''returns timeline data for the past one year'''
|
||||
from frappe.desk.form.load import get_communication_data
|
||||
|
@ -47,6 +47,12 @@ frappe.query_reports["General Ledger"] = {
|
||||
"label": __("Voucher No"),
|
||||
"fieldtype": "Data",
|
||||
},
|
||||
{
|
||||
"fieldname":"project",
|
||||
"label": __("Project"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"fieldtype": "Break",
|
||||
},
|
||||
|
@ -149,6 +149,9 @@ def get_conditions(filters):
|
||||
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
|
||||
conditions.append("posting_date >=%(from_date)s")
|
||||
|
||||
if filters.get("project"):
|
||||
conditions.append("project=%(project)s")
|
||||
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
match_conditions = build_match_conditions("GL Entry")
|
||||
if match_conditions: conditions.append(match_conditions)
|
||||
|
@ -21,20 +21,12 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
if(this.frm.get_field('shipping_address')) {
|
||||
this.frm.set_query("shipping_address", function(){
|
||||
if(me.frm.doc.customer){
|
||||
return{
|
||||
filters:{
|
||||
"customer": me.frm.doc.customer
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
return{
|
||||
filters:{
|
||||
"is_your_company_address": 1,
|
||||
"company": me.frm.doc.company
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
query: 'frappe.geo.doctype.address.address.address_query',
|
||||
filters: { link_doctype: 'Customer', link_name: me.frm.doc.customer }
|
||||
};
|
||||
} else
|
||||
return erpnext.queries.company_address_query(me.frm.doc)
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -26,11 +26,11 @@ frappe.ui.form.on("Supplier", {
|
||||
|
||||
if(frm.doc.__islocal){
|
||||
hide_field(['address_html','contact_html']);
|
||||
erpnext.utils.clear_address_and_contact(frm);
|
||||
frappe.geo.clear_address_and_contact(frm);
|
||||
}
|
||||
else {
|
||||
unhide_field(['address_html','contact_html']);
|
||||
erpnext.utils.render_address_and_contact(frm);
|
||||
frappe.geo.render_address_and_contact(frm);
|
||||
|
||||
// custom buttons
|
||||
frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
|
@ -6,7 +6,7 @@ import frappe
|
||||
import frappe.defaults
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.naming import make_autoname
|
||||
from erpnext.utilities.address_and_contact import (load_address_and_contact,
|
||||
from frappe.geo.address_and_contact import (load_address_and_contact,
|
||||
delete_contact_and_address)
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
@ -61,14 +61,6 @@ class Supplier(TransactionBase):
|
||||
validate_party_accounts(self)
|
||||
self.status = get_party_status(self)
|
||||
|
||||
def get_contacts(self,nm):
|
||||
if nm:
|
||||
contact_details =frappe.db.convert_to_lists(frappe.db.sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = %s", nm))
|
||||
|
||||
return contact_details
|
||||
else:
|
||||
return ''
|
||||
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Supplier', self.name)
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-10-09 10:38:40",
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2014-09-11 08:53:17.358554",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Addresses and Contacts",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as \"Contact Name::180\",\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Address::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc",
|
||||
"ref_doctype": "Supplier",
|
||||
"report_name": "Supplier Addresses and Contacts",
|
||||
"report_type": "Query Report"
|
||||
}
|
@ -172,8 +172,12 @@ def get_data():
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Supplier Addresses and Contacts",
|
||||
"doctype": "Supplier"
|
||||
"name": "Addresses And Contacts",
|
||||
"label": "Supplier Addresses And Contacts",
|
||||
"doctype": "Address",
|
||||
"route_options": {
|
||||
"party_type": "Supplier"
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
|
@ -265,6 +265,26 @@ def get_data():
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Employee Loan Management"),
|
||||
"icon": "icon-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Loan Type",
|
||||
"description": _("Define various loan types")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Loan Application",
|
||||
"description": _("Employee Loan Application")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Loan"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Help"),
|
||||
"icon": "fa fa-facetime-video",
|
||||
|
@ -159,23 +159,6 @@ def get_data():
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("LMS"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Announcement"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Topic"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Discussion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Setup"),
|
||||
"items": [
|
||||
|
@ -117,6 +117,16 @@ def get_data():
|
||||
"link": "Tree/Sales Person",
|
||||
"description": _("Manage Sales Person Tree."),
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Addresses And Contacts",
|
||||
"label": "Sales Partner Addresses And Contacts",
|
||||
"doctype": "Address",
|
||||
"route_options": {
|
||||
"party_type": "Sales Partner"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
@ -215,8 +225,12 @@ def get_data():
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Customer Addresses And Contacts",
|
||||
"doctype": "Contact"
|
||||
"name": "Addresses And Contacts",
|
||||
"label": "Customer Addresses And Contacts",
|
||||
"doctype": "Address",
|
||||
"route_options": {
|
||||
"party_type": "Customer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
|
@ -25,6 +25,7 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
refresh: function() {
|
||||
var doc = this.frm.doc;
|
||||
erpnext.toggle_naming_series();
|
||||
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'name', doctype: 'Lead'}
|
||||
|
||||
if(!this.frm.doc.__islocal && this.frm.doc.__onload && !this.frm.doc.__onload.is_customer) {
|
||||
this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make"));
|
||||
@ -34,9 +35,9 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
}
|
||||
|
||||
if(!this.frm.doc.__islocal) {
|
||||
erpnext.utils.render_address_and_contact(cur_frm);
|
||||
frappe.geo.render_address_and_contact(cur_frm);
|
||||
} else {
|
||||
erpnext.utils.clear_address_and_contact(cur_frm);
|
||||
frappe.geo.clear_address_and_contact(cur_frm);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -8,7 +8,7 @@ from frappe.utils import cstr, validate_email_add, cint, comma_and, has_gravatar
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from frappe.geo.address_and_contact import load_address_and_contact
|
||||
from erpnext.accounts.party import set_taxes
|
||||
|
||||
sender_field = "email_id"
|
||||
|
@ -106,30 +106,6 @@ class Opportunity(TransactionBase):
|
||||
lead_name, company_name = frappe.db.get_value("Lead", self.lead, ["lead_name", "company_name"])
|
||||
self.customer_name = company_name or lead_name
|
||||
|
||||
def get_cust_address(self,name):
|
||||
details = frappe.db.sql("""select customer_name, address, territory, customer_group
|
||||
from `tabCustomer` where name = %s and docstatus != 2""", (name), as_dict = 1)
|
||||
if details:
|
||||
ret = {
|
||||
'customer_name': details and details[0]['customer_name'] or '',
|
||||
'address' : details and details[0]['address'] or '',
|
||||
'territory' : details and details[0]['territory'] or '',
|
||||
'customer_group' : details and details[0]['customer_group'] or ''
|
||||
}
|
||||
# ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
|
||||
|
||||
contact_det = frappe.db.sql("""select contact_name, contact_no, email_id
|
||||
from `tabContact` where customer = %s and is_customer = 1
|
||||
and is_primary_contact = 'Yes' and docstatus != 2""", name, as_dict = 1)
|
||||
|
||||
ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
|
||||
ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or ''
|
||||
ret['email_id'] = contact_det and contact_det[0]['email_id'] or ''
|
||||
|
||||
return ret
|
||||
else:
|
||||
frappe.throw(_("Customer {0} does not exist").format(name), frappe.DoesNotExistError)
|
||||
|
||||
def on_update(self):
|
||||
self.add_calendar_event()
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 209 KiB |
BIN
erpnext/docs/assets/img/human-resources/employee-loan.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/employee-loan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 380 KiB |
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
BIN
erpnext/docs/assets/img/human-resources/loan-type.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/loan-type.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
BIN
erpnext/docs/assets/img/human-resources/repayment-info.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/repayment-info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
erpnext/docs/assets/img/human-resources/repayment-schedule.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/repayment-schedule.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 424 KiB |
@ -0,0 +1,56 @@
|
||||
# Employee Loan Management
|
||||
This module enables companies which provides employee loans to define and manage employee loans.
|
||||
Employees can request loans, which are then reviewed and approved. For the approved loans,
|
||||
repayment schedule for the entire loan cycle can be generated and automatic deduction from salary can also be set up.
|
||||
|
||||
### Loan Type
|
||||
To create a new Loan Type go to:
|
||||
|
||||
> Human Resources > Employee Loan Management > Loan Type > New Loan Type
|
||||
|
||||
Configure Loan limit and Rate of interest.
|
||||
|
||||
<img class="screenshot" alt="Loan Type" src="{{docs_base_url}}/assets/img/human-resources/loan-type.png">
|
||||
|
||||
### Employee Loan Application
|
||||
|
||||
Employee can apply for loan by going to:
|
||||
|
||||
> Human Resources > Employee Loan Management > Employee Loan Application > New Employee Loan Application
|
||||
|
||||
<img class="screenshot" alt="Employee Loan Application" src="{{docs_base_url}}/assets/img/human-resources/employee-loan-application.png">
|
||||
|
||||
#### In the Employee Loan Application,
|
||||
|
||||
* Enter Employee details and Loan details
|
||||
* Select the repayment method, and based on your selection enter Repayment Period in Months or repayment Amount
|
||||
|
||||
On save, Employee can see Repayment Information and make changes if required before submitting.
|
||||
|
||||
<img class="screenshot" alt="Employee Loan Application" src="{{docs_base_url}}/assets/img/human-resources/repayment-info.png">
|
||||
|
||||
### Employee Loan
|
||||
|
||||
Once the Loan is approved, Manager can create Employee Loan record for the Employee.
|
||||
|
||||
> Human Resources > Employee Loan Management > Employee Loan > New Employee Loan
|
||||
|
||||
<img class="screenshot" alt="Employee Loan Application" src="{{docs_base_url}}/assets/img/human-resources/employee-loan.png">
|
||||
|
||||
#### In the Employee Loan,
|
||||
|
||||
* Enter Employee and Loan Application
|
||||
* Check "Repay from Salary" if the loan repayment will be deducted from the salary
|
||||
* Enter Disbursement Date and Account Info
|
||||
* As soon as you hit save, the repayment schedule is generated.
|
||||
|
||||
<img class="screenshot" alt="repayment Schedule" src="{{docs_base_url}}/assets/img/human-resources/repayment-schedule.png">
|
||||
|
||||
#### Loan repayment deduction from Salary
|
||||
|
||||
To auto deduct the Loan repayment from Salary, check "Repay from Salary" in Employee Loan. It will appear as Loan repayment in Salary Slip.
|
||||
|
||||
<img class="screenshot" alt="Salary Slip" src="{{docs_base_url}}/assets/img/human-resources/loan-repayment-salary-slip.png">
|
||||
|
||||
|
||||
|
@ -15,4 +15,5 @@ holiday-list
|
||||
human-resource-setup
|
||||
daily-work-summary
|
||||
fleet-management
|
||||
employee-loan-management
|
||||
articles
|
||||
|
@ -107,7 +107,6 @@ portal_menu_items = [
|
||||
{"title": _("Shipments"), "route": "/shipments", "reference_doctype": "Delivery Note", "role":"Customer"},
|
||||
{"title": _("Issues"), "route": "/issues", "reference_doctype": "Issue", "role":"Customer"},
|
||||
{"title": _("Addresses"), "route": "/addresses", "reference_doctype": "Address"},
|
||||
{"title": _("Announcements"), "route": "/announcement", "reference_doctype": "Announcement"},
|
||||
{"title": _("Fees"), "route": "/fees", "reference_doctype": "Fees", "role":"Student"}
|
||||
]
|
||||
|
||||
@ -122,18 +121,7 @@ has_website_permission = {
|
||||
"Sales Invoice": "erpnext.controllers.website_list_for_contact.has_website_permission",
|
||||
"Supplier Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission",
|
||||
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission",
|
||||
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission",
|
||||
"Discussion": "erpnext.schools.web_form.discussion.discussion.has_website_permission"
|
||||
}
|
||||
|
||||
permission_query_conditions = {
|
||||
"Contact": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_contact",
|
||||
"Address": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_address"
|
||||
}
|
||||
|
||||
has_permission = {
|
||||
"Contact": "erpnext.utilities.address_and_contact.has_permission",
|
||||
"Address": "erpnext.utilities.address_and_contact.has_permission"
|
||||
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission"
|
||||
}
|
||||
|
||||
dump_report_map = "erpnext.startup.report_data_map.data_map"
|
||||
@ -153,7 +141,7 @@ doc_events = {
|
||||
"after_insert": "frappe.email.doctype.contact.contact.update_contact",
|
||||
"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
|
||||
"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions",
|
||||
"on_update": "erpnext.utilities.address_and_contact.set_default_role"
|
||||
"on_update": "frappe.geo.address_and_contact.set_default_role"
|
||||
},
|
||||
("Sales Taxes and Charges Template", 'Price List'): {
|
||||
"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
|
||||
|
88
erpnext/hr/doctype/employee_loan/employee_loan.js
Normal file
88
erpnext/hr/doctype/employee_loan/employee_loan.js
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Loan', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("employee_loan_application", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"employee": frm.doc.employee,
|
||||
"docstatus": 1,
|
||||
"status": "Approved"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
$.each(["payment_account", "employee_loan_account"], function(i, field) {
|
||||
frm.set_query(field, function() {
|
||||
return {
|
||||
"filters": {
|
||||
"company": frm.doc.company,
|
||||
"root_type": "Asset",
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
mode_of_payment: function(frm){
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
|
||||
args: {
|
||||
"mode_of_payment": frm.doc.mode_of_payment,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
frm.set_value("payment_account", r.message.account);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
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",
|
||||
args: {
|
||||
"employee_loan_application": frm.doc.employee_loan_application
|
||||
},
|
||||
callback: function(r){
|
||||
if(!r.exc && r.message) {
|
||||
frm.set_value("loan_type", r.message.loan_type);
|
||||
frm.set_value("loan_amount", r.message.loan_amount);
|
||||
frm.set_value("repayment_method", r.message.repayment_method);
|
||||
frm.set_value("monthly_repayment_amount", r.message.repayment_amount);
|
||||
frm.set_value("repayment_periods", r.message.repayment_periods);
|
||||
frm.set_value("rate_of_interest", r.message.rate_of_interest);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
repayment_method: function(frm) {
|
||||
frm.trigger("toggle_fields")
|
||||
},
|
||||
|
||||
toggle_fields: function(frm) {
|
||||
frm.toggle_enable("monthly_repayment_amount", frm.doc.repayment_method=="Repay Fixed Amount per Period")
|
||||
frm.toggle_enable("repayment_periods", frm.doc.repayment_method=="Repay Over Number of Periods")
|
||||
}
|
||||
});
|
892
erpnext/hr/doctype/employee_loan/employee_loan.json
Normal file
892
erpnext/hr/doctype/employee_loan/employee_loan.json
Normal file
@ -0,0 +1,892 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ELN.####",
|
||||
"beta": 0,
|
||||
"creation": "2016-12-02 10:11:49.673604",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"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_list_view": 0,
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "employee.employee_name",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_loan_application",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Loan Application",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Loan Application",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Loan Type",
|
||||
"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_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_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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"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_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": 1,
|
||||
"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": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Loan Unpaid\nLoan Paid\nEMI in progress\nLoan Repaid",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "repay_from_salary",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repay from Salary",
|
||||
"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_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_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "rate_of_interest",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate of Interest (%) / Year",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "loan_type.rate_of_interest",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disbursement_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disbursement 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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Repay Over Number of Periods",
|
||||
"fieldname": "repayment_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Method",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nRepay Fixed Amount per Period\nRepay Over Number of Periods",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "",
|
||||
"fieldname": "repayment_periods",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Period in Months",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "",
|
||||
"fieldname": "monthly_repayment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "account_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Account Info",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Mode of Payment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Mode of Payment",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "payment_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Account",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_loan_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Loan Account",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_15",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Schedule",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "repayment_schedule",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Schedule",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Repayment Schedule",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_17",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Totals",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "total_payment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Payment",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "total_interest_payable",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Interest Payable",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"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_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Employee Loan",
|
||||
"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,
|
||||
"unique": 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-01-17 07:13:10.704520",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Loan",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "posting_date",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
128
erpnext/hr/doctype/employee_loan/employee_loan.py
Normal file
128
erpnext/hr/doctype/employee_loan/employee_loan.py
Normal file
@ -0,0 +1,128 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, math
|
||||
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):
|
||||
check_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
||||
if not self.company:
|
||||
self.company = erpnext.get_default_company()
|
||||
if not self.posting_date:
|
||||
self.posting_date = nowdate()
|
||||
if self.loan_type and not self.rate_of_interest:
|
||||
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
|
||||
if self.repayment_method == "Repay Over Number of Periods":
|
||||
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||
|
||||
self.make_repayment_schedule()
|
||||
self.set_repayment_period()
|
||||
self.calculate_totals()
|
||||
|
||||
def on_submit(self):
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.make_gl_entries()
|
||||
|
||||
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
|
||||
})
|
||||
)
|
||||
# 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
|
||||
})
|
||||
)
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2))
|
||||
|
||||
def make_repayment_schedule(self):
|
||||
self.repayment_schedule = []
|
||||
payment_date = self.disbursement_date
|
||||
balance_amount = self.loan_amount
|
||||
|
||||
while(balance_amount > 0):
|
||||
interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12*100))
|
||||
principal_amount = self.monthly_repayment_amount - interest_amount
|
||||
balance_amount = rounded(balance_amount + interest_amount - self.monthly_repayment_amount)
|
||||
|
||||
if balance_amount < 0:
|
||||
principal_amount += balance_amount
|
||||
balance_amount = 0.0
|
||||
|
||||
total_payment = principal_amount + interest_amount
|
||||
|
||||
self.append("repayment_schedule", {
|
||||
"payment_date": payment_date,
|
||||
"principal_amount": principal_amount,
|
||||
"interest_amount": interest_amount,
|
||||
"total_payment": total_payment,
|
||||
"balance_loan_amount": balance_amount
|
||||
})
|
||||
|
||||
next_payment_date = add_months(payment_date, 1)
|
||||
payment_date = next_payment_date
|
||||
|
||||
def set_repayment_period(self):
|
||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
||||
repayment_periods = len(self.repayment_schedule)
|
||||
|
||||
self.repayment_periods = repayment_periods
|
||||
|
||||
def calculate_totals(self):
|
||||
self.total_payment = 0
|
||||
self.total_interest_payable = 0
|
||||
for data in self.repayment_schedule:
|
||||
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 check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
||||
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
|
||||
frappe.throw(_("Please enter Repayment Periods"))
|
||||
|
||||
if repayment_method == "Repay Fixed Amount per Period":
|
||||
if not monthly_repayment_amount:
|
||||
frappe.throw(_("Please enter repayment Amount"))
|
||||
if monthly_repayment_amount > loan_amount:
|
||||
frappe.throw(_("Monthly Repayment Amount cannot be greater than Loan Amount"))
|
||||
|
||||
def get_monthly_repayment_amount(repayment_method, loan_amount, rate_of_interest, repayment_periods):
|
||||
if repayment_method == "Repay Over Number of Periods":
|
||||
if rate_of_interest:
|
||||
monthly_interest_rate = flt(rate_of_interest) / (12 *100)
|
||||
monthly_repayment_amount = math.ceil((loan_amount * monthly_interest_rate *
|
||||
(1 + monthly_interest_rate)**repayment_periods) \
|
||||
/ ((1 + monthly_interest_rate)**repayment_periods - 1))
|
||||
else:
|
||||
monthly_repayment_amount = math.ceil(flt(loan_amount) / repayment_periods)
|
||||
return monthly_repayment_amount
|
||||
|
||||
@frappe.whitelist()
|
||||
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
|
68
erpnext/hr/doctype/employee_loan/test_employee_loan.py
Normal file
68
erpnext/hr/doctype/employee_loan/test_employee_loan.py
Normal file
@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import erpnext
|
||||
import unittest
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee
|
||||
|
||||
class TestEmployeeLoan(unittest.TestCase):
|
||||
def setUp(self):
|
||||
create_loan_type("Personal Loan", 500000, 8.4)
|
||||
self.employee = make_employee("robert_loan@loan.com")
|
||||
create_employee_loan(self.employee, "Personal Loan", 280000, "Repay Over Number of Periods", 20)
|
||||
|
||||
def test_employee_loan(self):
|
||||
employee_loan = frappe.get_doc("Employee Loan", {"employee":self.employee})
|
||||
self.assertEquals(employee_loan.monthly_repayment_amount, 15052)
|
||||
self.assertEquals(employee_loan.total_interest_payable, 21034)
|
||||
self.assertEquals(employee_loan.total_payment, 301034)
|
||||
|
||||
schedule = employee_loan.repayment_schedule
|
||||
|
||||
self.assertEquals(len(schedule), 20)
|
||||
|
||||
for idx, principal_amount, interest_amount, balance_loan_amount in [[3, 13369, 1683, 227079], [19, 14941, 105, 0], [17, 14740, 312, 29785]]:
|
||||
self.assertEquals(schedule[idx].principal_amount, principal_amount)
|
||||
self.assertEquals(schedule[idx].interest_amount, interest_amount)
|
||||
self.assertEquals(schedule[idx].balance_loan_amount, balance_loan_amount)
|
||||
|
||||
employee_loan.repayment_method = "Repay Fixed Amount per Period"
|
||||
employee_loan.monthly_repayment_amount = 14000
|
||||
employee_loan.save()
|
||||
|
||||
self.assertEquals(len(employee_loan.repayment_schedule), 22)
|
||||
self.assertEquals(employee_loan.total_interest_payable, 22712)
|
||||
self.assertEquals(employee_loan.total_payment, 302712)
|
||||
|
||||
|
||||
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest):
|
||||
if not frappe.db.get_value("Loan Type", loan_name):
|
||||
frappe.get_doc({
|
||||
"doctype": "Loan Type",
|
||||
"loan_name": loan_name,
|
||||
"maximum_loan_amount": maximum_loan_amount,
|
||||
"rate_of_interest": rate_of_interest
|
||||
}).insert()
|
||||
|
||||
def create_employee_loan(employee, loan_type, loan_amount, repayment_method, repayment_periods):
|
||||
if not frappe.db.get_value("Employee Loan", {"employee":employee}):
|
||||
employee_loan = frappe.new_doc("Employee Loan")
|
||||
employee_loan.update({
|
||||
"employee": employee,
|
||||
"loan_type": loan_type,
|
||||
"loan_amount": loan_amount,
|
||||
"repayment_method": repayment_method,
|
||||
"repayment_periods": repayment_periods,
|
||||
"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.insert()
|
||||
return employee_loan
|
||||
else:
|
||||
return frappe.get_doc("Employee Loan", {"employee":employee})
|
@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Loan Application', {
|
||||
refresh: function(frm) {
|
||||
frm.trigger("toggle_fields")
|
||||
},
|
||||
repayment_method: function(frm) {
|
||||
frm.trigger("toggle_fields")
|
||||
},
|
||||
|
||||
toggle_fields: function(frm) {
|
||||
frm.toggle_enable("repayment_amount", frm.doc.repayment_method=="Repay Fixed Amount per Period")
|
||||
frm.toggle_enable("repayment_periods", frm.doc.repayment_method=="Repay Over Number of Periods")
|
||||
}
|
||||
});
|
@ -0,0 +1,681 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ELA/.#####",
|
||||
"beta": 0,
|
||||
"creation": "2016-12-02 12:35:56.046811",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting 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,
|
||||
"unique": 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_list_view": 0,
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "employee.employee_name",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"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_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_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Open\nApproved\nRejected",
|
||||
"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_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_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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Info",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Loan Type",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "required_by_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Required by 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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reason",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "repayment_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Info",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "repayment_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Method",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nRepay Fixed Amount per Period\nRepay Over Number of Periods",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate_of_interest",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate of Interest",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "loan_type.rate_of_interest",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_payable_interest",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Payable Interest",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "repayment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "repayment_periods",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Repayment Period in Months",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_payable_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Payable Amount",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"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_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Employee Loan Application",
|
||||
"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,
|
||||
"unique": 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-01-09 12:02:36.562577",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Loan Application",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Employee",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "employee, employee_name, loan_type, loan_amount",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "employee",
|
||||
"title_field": "employee_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, math
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.model.document import Document
|
||||
|
||||
from erpnext.hr.doctype.employee_loan.employee_loan import get_monthly_repayment_amount, check_repayment_method
|
||||
|
||||
class EmployeeLoanApplication(Document):
|
||||
def validate(self):
|
||||
check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
||||
self.validate_loan_amount()
|
||||
self.get_repayment_details()
|
||||
|
||||
def validate_loan_amount(self):
|
||||
maximum_loan_limit = frappe.db.get_value('Loan Type', self.loan_type, 'maximum_loan_amount')
|
||||
if self.loan_amount > maximum_loan_limit:
|
||||
frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit))
|
||||
|
||||
def get_repayment_details(self):
|
||||
if self.repayment_method == "Repay Over Number of Periods":
|
||||
self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||
|
||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
||||
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
|
||||
self.repayment_periods = math.ceil((math.log(self.repayment_amount) - math.log(self.repayment_amount - \
|
||||
(self.loan_amount*monthly_interest_rate)))/(math.log(1+monthly_interest_rate)))
|
||||
|
||||
self.total_payable_amount = self.repayment_amount * self.repayment_periods
|
||||
self.total_payable_interest = self.total_payable_amount - self.loan_amount
|
@ -0,0 +1,51 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee
|
||||
|
||||
class TestEmployeeLoanApplication(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.create_loan_type()
|
||||
self.employee = make_employee("kate_loan@loan.com")
|
||||
self.create_loan_application()
|
||||
|
||||
def create_loan_type(self):
|
||||
if not frappe.db.get_value("Loan Type", "Home Loan"):
|
||||
frappe.get_doc({
|
||||
"doctype": "Loan Type",
|
||||
"loan_name": "Home Loan",
|
||||
"maximum_loan_amount": 500000,
|
||||
"rate_of_interest": 9.2
|
||||
}).insert()
|
||||
|
||||
def create_loan_application(self):
|
||||
if not frappe.db.get_value("Employee Loan Application", {"employee":self.employee}, "name"):
|
||||
loan_application = frappe.new_doc("Employee Loan Application")
|
||||
loan_application.update({
|
||||
"employee": self.employee,
|
||||
"loan_type": "Home Loan",
|
||||
"rate_of_interest": 9.2,
|
||||
"loan_amount": 250000,
|
||||
"repayment_method": "Repay Over Number of Periods",
|
||||
"repayment_periods": 24
|
||||
})
|
||||
loan_application.insert()
|
||||
|
||||
|
||||
def test_loan_totals(self):
|
||||
loan_application = frappe.get_doc("Employee Loan Application", {"employee":self.employee})
|
||||
self.assertEquals(loan_application.repayment_amount, 11445)
|
||||
self.assertEquals(loan_application.total_payable_interest, 24680)
|
||||
self.assertEquals(loan_application.total_payable_amount, 274680)
|
||||
|
||||
loan_application.repayment_method = "Repay Fixed Amount per Period"
|
||||
loan_application.repayment_amount = 15000
|
||||
loan_application.save()
|
||||
|
||||
self.assertEquals(loan_application.repayment_periods, 18)
|
||||
self.assertEquals(loan_application.total_payable_interest, 20000)
|
||||
self.assertEquals(loan_application.total_payable_amount, 270000)
|
7
erpnext/hr/doctype/loan_type/loan_type.js
Normal file
7
erpnext/hr/doctype/loan_type/loan_type.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Loan Type', {
|
||||
refresh: function(frm) {
|
||||
}
|
||||
});
|
@ -1,15 +1,15 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "Discussion.####",
|
||||
"autoname": "field:loan_name",
|
||||
"beta": 0,
|
||||
"creation": "2016-06-13 07:57:38.326925",
|
||||
"creation": "2016-12-02 10:41:40.732843",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
@ -17,7 +17,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "subject",
|
||||
"fieldname": "loan_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -25,7 +25,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Subject",
|
||||
"label": "Loan Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -36,7 +36,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@ -45,18 +45,17 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "course",
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "maximum_loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Course",
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Maximum Loan Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Course",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -65,7 +64,92 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate_of_interest",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate of Interest (%) Yearly",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_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_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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disabled",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@ -96,34 +180,6 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 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_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Discussion",
|
||||
"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,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@ -132,14 +188,14 @@
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-11-07 05:28:34.032169",
|
||||
"modified": "2016-12-29 15:54:17.716285",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Schools",
|
||||
"name": "Discussion",
|
||||
"module": "HR",
|
||||
"name": "Loan Type",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
@ -158,18 +214,17 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Academics User",
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "subject",
|
||||
"track_seen": 1
|
||||
"track_seen": 0
|
||||
}
|
10
erpnext/hr/doctype/loan_type/loan_type.py
Normal file
10
erpnext/hr/doctype/loan_type/loan_type.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class LoanType(Document):
|
||||
pass
|
12
erpnext/hr/doctype/loan_type/test_loan_type.py
Normal file
12
erpnext/hr/doctype/loan_type/test_loan_type.py
Normal file
@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Loan Type')
|
||||
|
||||
class TestLoanType(unittest.TestCase):
|
||||
pass
|
@ -1,60 +1,30 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "Topic.####",
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-06-28 07:06:38.749398",
|
||||
"creation": "2016-12-20 15:32:25.078334",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "course",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"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": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "topic_name",
|
||||
"fieldtype": "Data",
|
||||
"columns": 2,
|
||||
"fieldname": "payment_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Topic Name",
|
||||
"label": "Payment Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -64,7 +34,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -73,26 +43,26 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "introduction",
|
||||
"fieldtype": "Text",
|
||||
"columns": 2,
|
||||
"fieldname": "principal_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Introduction",
|
||||
"label": "Principal Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -101,26 +71,82 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "content",
|
||||
"fieldtype": "Text Editor",
|
||||
"columns": 2,
|
||||
"fieldname": "interest_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Content",
|
||||
"label": "Interest Amount",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "total_payment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Payment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "balance_loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Balance Loan Amount",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"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
|
||||
@ -134,42 +160,20 @@
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-11-07 05:29:20.531725",
|
||||
"modified": "2017-01-09 12:00:10.818772",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Schools",
|
||||
"name": "Topic",
|
||||
"module": "HR",
|
||||
"name": "Repayment Schedule",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Academics User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "course",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
10
erpnext/hr/doctype/repayment_schedule/repayment_schedule.py
Normal file
10
erpnext/hr/doctype/repayment_schedule/repayment_schedule.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class RepaymentSchedule(Document):
|
||||
pass
|
@ -110,6 +110,7 @@ cur_frm.cscript.depends_on_lwp = function(doc,dt,dn){
|
||||
calculate_earning_total(doc, dt, dn, true);
|
||||
calculate_ded_total(doc, dt, dn, true);
|
||||
calculate_net_pay(doc, dt, dn);
|
||||
refresh_many(['amount','gross_pay', 'rounded_total', 'net_pay', 'loan_repayment']);
|
||||
};
|
||||
|
||||
// Calculate earning total
|
||||
|
@ -1266,7 +1266,35 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Gross Pay + Arrear Amount +Encashment Amount - Total Deduction",
|
||||
"fieldname": "loan_repayment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Loan Repayment",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Gross Pay + Arrear Amount + Encashment Amount - Total Deduction - Loan Repayment",
|
||||
"fieldname": "net_pay",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -1362,7 +1390,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-12-14 08:26:31.400930",
|
||||
"modified": "2017-01-09 12:37:03.802501",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip",
|
||||
@ -1413,7 +1441,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -1430,6 +1458,7 @@
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"user_permission_doctypes": "[\"Employee\"]",
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
@ -1440,5 +1469,6 @@
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "employee",
|
||||
"title_field": "employee_name",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
@ -330,10 +330,20 @@ class SalarySlip(TransactionBase):
|
||||
self.sum_components('earnings', 'gross_pay')
|
||||
self.sum_components('deductions', 'total_deduction')
|
||||
|
||||
self.net_pay = flt(self.gross_pay) - flt(self.total_deduction)
|
||||
self.set_loan_repayment()
|
||||
|
||||
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.loan_repayment))
|
||||
self.rounded_total = rounded(self.net_pay,
|
||||
self.precision("net_pay") if disable_rounded_total else 0)
|
||||
|
||||
def set_loan_repayment(self):
|
||||
employee_loan = frappe.db.sql("""select sum(total_payment) as loan_repayment from `tabRepayment Schedule`
|
||||
where payment_date between %s and %s and parent in (select name from `tabEmployee Loan`
|
||||
where employee = %s and repay_from_salary = 1 and docstatus = 1)""",
|
||||
(self.start_date, self.end_date, self.employee), as_dict=True)
|
||||
if employee_loan:
|
||||
self.loan_repayment = employee_loan[0].loan_repayment
|
||||
|
||||
def on_submit(self):
|
||||
if self.net_pay < 0:
|
||||
frappe.throw(_("Net Pay cannot be less than 0"))
|
||||
|
@ -7,7 +7,7 @@ import frappe
|
||||
import erpnext
|
||||
import calendar
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from frappe.utils import getdate, nowdate, add_days
|
||||
from frappe.utils import getdate, nowdate, add_days, flt
|
||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.hr.doctype.process_payroll.test_process_payroll import get_salary_component_account
|
||||
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
|
||||
@ -24,7 +24,6 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
||||
frappe.set_user("Administrator")
|
||||
@ -40,12 +39,12 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
self.assertEquals(ss.total_working_days, no_of_days[0])
|
||||
self.assertEquals(ss.payment_days, no_of_days[0])
|
||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||
self.assertEquals(ss.earnings[0].amount, 25000)
|
||||
self.assertEquals(ss.earnings[1].amount, 3000)
|
||||
self.assertEquals(ss.deductions[0].amount, 5000)
|
||||
self.assertEquals(ss.deductions[1].amount, 2500)
|
||||
self.assertEquals(ss.gross_pay, 10500)
|
||||
self.assertEquals(ss.net_pay, 3000)
|
||||
self.assertEquals(ss.deductions[1].amount, 5000)
|
||||
self.assertEquals(ss.gross_pay, 40500)
|
||||
self.assertEquals(ss.net_pay, 29918)
|
||||
|
||||
def test_salary_slip_with_holidays_excluded(self):
|
||||
no_of_days = self.get_no_of_days()
|
||||
@ -58,13 +57,13 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
self.assertEquals(ss.total_working_days, no_of_days[0] - no_of_days[1])
|
||||
self.assertEquals(ss.payment_days, no_of_days[0] - no_of_days[1])
|
||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||
self.assertEquals(ss.earnings[0].default_amount, 5000)
|
||||
self.assertEquals(ss.earnings[0].amount, 25000)
|
||||
self.assertEquals(ss.earnings[0].default_amount, 25000)
|
||||
self.assertEquals(ss.earnings[1].amount, 3000)
|
||||
self.assertEquals(ss.deductions[0].amount, 5000)
|
||||
self.assertEquals(ss.deductions[1].amount, 2500)
|
||||
self.assertEquals(ss.gross_pay, 10500)
|
||||
self.assertEquals(ss.net_pay, 3000)
|
||||
self.assertEquals(ss.deductions[1].amount, 5000)
|
||||
self.assertEquals(ss.gross_pay, 40500)
|
||||
self.assertEquals(ss.net_pay, 29918)
|
||||
|
||||
def test_payment_days(self):
|
||||
no_of_days = self.get_no_of_days()
|
||||
@ -130,9 +129,23 @@ class TestSalarySlip(unittest.TestCase):
|
||||
ss = frappe.get_doc("Salary Slip",
|
||||
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||
ss.submit()
|
||||
|
||||
email_queue = frappe.db.sql("""select name from `tabEmail Queue`""")
|
||||
self.assertTrue(email_queue)
|
||||
|
||||
def test_loan_repayment_salary_slip(self):
|
||||
from erpnext.hr.doctype.employee_loan.test_employee_loan import create_loan_type, create_employee_loan
|
||||
employee = self.make_employee("test_employee@salary.com")
|
||||
create_loan_type("Car Loan", 500000, 6.4)
|
||||
employee_loan = create_employee_loan(employee, "Car Loan", 11000, "Repay Over Number of Periods", 20)
|
||||
employee_loan.repay_from_salary = 1
|
||||
employee_loan.submit()
|
||||
ss = frappe.get_doc("Salary Slip",
|
||||
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||
ss.submit()
|
||||
self.assertEquals(ss.loan_repayment, 582)
|
||||
self.assertEquals(ss.net_pay, (flt(ss.gross_pay) - (flt(ss.total_deduction) + flt(ss.loan_repayment))))
|
||||
|
||||
def test_payroll_frequency(self):
|
||||
fiscal_year = get_fiscal_year(nowdate(), company="_Test Company")[0]
|
||||
month = "%02d" % getdate(nowdate()).month
|
||||
@ -167,7 +180,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.get_value("Employee", {"user_id": user}):
|
||||
frappe.get_doc({
|
||||
employee = frappe.get_doc({
|
||||
"doctype": "Employee",
|
||||
"naming_series": "EMP-",
|
||||
"employee_name": user,
|
||||
@ -183,6 +196,9 @@ class TestSalarySlip(unittest.TestCase):
|
||||
"status": "Active",
|
||||
"employment_type": "Intern"
|
||||
}).insert()
|
||||
return employee.name
|
||||
else:
|
||||
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
||||
|
||||
def make_holiday_list(self):
|
||||
fiscal_year = get_fiscal_year(nowdate(), company="_Test Company")
|
||||
@ -278,7 +294,7 @@ def make_salary_structure(sal_struct, payroll_frequency, employee):
|
||||
|
||||
def get_employee_details(employee):
|
||||
return [{"employee": employee,
|
||||
"base": 25000,
|
||||
"base": 50000,
|
||||
"variable": 5000
|
||||
}
|
||||
]
|
||||
@ -289,14 +305,14 @@ def get_earnings_component():
|
||||
"salary_component": 'Basic Salary',
|
||||
"abbr":'BS',
|
||||
"condition": 'base > 10000',
|
||||
"formula": 'base*.2',
|
||||
"formula": 'base*.5',
|
||||
"idx": 1
|
||||
},
|
||||
{
|
||||
"salary_component": 'Basic Salary',
|
||||
"abbr":'BS',
|
||||
"condition": 'base < 10000',
|
||||
"formula": 'base*.1',
|
||||
"formula": 'base*.2',
|
||||
"idx": 2
|
||||
},
|
||||
{
|
||||
@ -320,13 +336,13 @@ def get_deductions_component():
|
||||
"salary_component": 'Professional Tax',
|
||||
"abbr":'PT',
|
||||
"condition": 'base > 10000',
|
||||
"formula": 'base*.2',
|
||||
"formula": 'base*.1',
|
||||
"idx": 1
|
||||
},
|
||||
{
|
||||
"salary_component": 'TDS',
|
||||
"abbr":'T',
|
||||
"formula": 'base*.5',
|
||||
"formula": 'base*.1',
|
||||
"idx": 2
|
||||
},
|
||||
{
|
||||
|
@ -19,8 +19,8 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
||||
make_earning_salary_component(["Basic Salary", "Allowance", "HRA"])
|
||||
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||
self.make_employee("test_employee@salary.com")
|
||||
self.make_employee("test_employee_2@salary.com")
|
||||
make_employee("test_employee@salary.com")
|
||||
make_employee("test_employee_2@salary.com")
|
||||
|
||||
def make_holiday_list(self):
|
||||
if not frappe.db.get_value("Holiday List", "Salary Structure Test Holiday List"):
|
||||
@ -34,7 +34,18 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
holiday_list.get_weekly_off_dates()
|
||||
holiday_list.save()
|
||||
|
||||
def make_employee(self, user):
|
||||
def test_amount_totals(self):
|
||||
sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee@salary.com"})
|
||||
if not sal_slip:
|
||||
sal_slip = make_salary_slip_from_salary_structure(employee=frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}))
|
||||
self.assertEquals(sal_slip.get("salary_structure"), 'Salary Structure Sample')
|
||||
self.assertEquals(sal_slip.get("earnings")[0].amount, 5000)
|
||||
self.assertEquals(sal_slip.get("deductions")[0].amount, 5000)
|
||||
self.assertEquals(sal_slip.get("deductions")[1].amount, 2500)
|
||||
self.assertEquals(sal_slip.get("total_deduction"), 7500)
|
||||
self.assertEquals(sal_slip.get("net_pay"), 7500)
|
||||
|
||||
def make_employee(user):
|
||||
if not frappe.db.get_value("User", user):
|
||||
frappe.get_doc({
|
||||
"doctype": "User",
|
||||
@ -65,18 +76,6 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
else:
|
||||
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
||||
|
||||
def test_amount_totals(self):
|
||||
sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee@salary.com"})
|
||||
if not sal_slip:
|
||||
sal_slip = make_salary_slip_from_salary_structure(employee=frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}))
|
||||
self.assertEquals(sal_slip.get("salary_structure"), 'Salary Structure Sample')
|
||||
self.assertEquals(sal_slip.get("earnings")[0].amount, 5000)
|
||||
self.assertEquals(sal_slip.get("deductions")[0].amount, 5000)
|
||||
self.assertEquals(sal_slip.get("deductions")[1].amount, 2500)
|
||||
self.assertEquals(sal_slip.get("total_deduction"), 7500)
|
||||
self.assertEquals(sal_slip.get("net_pay"), 7500)
|
||||
|
||||
|
||||
def make_salary_slip_from_salary_structure(employee):
|
||||
sal_struct = make_salary_structure('Salary Structure Sample')
|
||||
sal_slip = make_salary_slip(sal_struct, employee = employee)
|
||||
|
@ -30,15 +30,18 @@ def get_columns(leave_types):
|
||||
return columns
|
||||
|
||||
def get_data(filters, leave_types):
|
||||
|
||||
user = frappe.session.user
|
||||
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
|
||||
|
||||
active_employees = frappe.get_all("Employee",
|
||||
filters = { "status": "Active", "company": filters.company},
|
||||
fields = ["name", "employee_name", "department"])
|
||||
fields = ["name", "employee_name", "department", "user_id"])
|
||||
|
||||
data = []
|
||||
for employee in active_employees:
|
||||
leave_approvers = [l.leave_approver for l in frappe.db.sql("""select leave_approver from `tabEmployee Leave Approver` where parent = %s""",
|
||||
(employee.name),as_dict=True)]
|
||||
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
|
||||
row = [employee.name, employee.employee_name, employee.department]
|
||||
|
||||
for leave_type in leave_types:
|
||||
|
@ -8,7 +8,7 @@ from erpnext.setup.setup_wizard import domainify
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype('Role')
|
||||
for dt in ("assessment", "announcement", "course", "fees"):
|
||||
for dt in ("assessment", "course", "fees"):
|
||||
frappe.reload_doc("schools", "doctype", dt)
|
||||
|
||||
frappe.reload_doc('website', 'doctype', 'portal_menu_item')
|
||||
|
@ -20,7 +20,8 @@ def execute():
|
||||
frappe.reload_doc("schools", "doctype", "evaluation_criteria")
|
||||
|
||||
|
||||
for assessment in frappe.get_all("Assessment Plan", fields=["name", "grading_scale"]):
|
||||
for assessment in frappe.get_all("Assessment Plan", fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
|
||||
print assessment
|
||||
for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s", assessment.name, as_dict=True):
|
||||
if stud_result.result:
|
||||
assessment_result = frappe.new_doc("Assessment Result")
|
||||
@ -30,6 +31,7 @@ def execute():
|
||||
assessment_result.grading_scale = assessment.grading_scale
|
||||
assessment_result.total_score = stud_result.result
|
||||
assessment_result.flags.ignore_validate = True
|
||||
assessment_result.flags.ignore_mandatory = True
|
||||
assessment_result.save()
|
||||
|
||||
frappe.db.sql("""delete from `tabAssessment Result` where parent != '' or parent is not null""")
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "TASK.#####",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-29 19:25:50",
|
||||
@ -944,7 +944,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 5,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-11-07 05:12:23.294476",
|
||||
"modified": "2017-01-27 01:26:24.985167",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Task",
|
||||
@ -960,7 +960,6 @@
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
@ -979,5 +978,6 @@
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "project",
|
||||
"title_field": "subject",
|
||||
"track_changes": 0,
|
||||
"track_seen": 1
|
||||
}
|
@ -31,7 +31,8 @@ erpnext.financial_statements = {
|
||||
"account": data.account,
|
||||
"company": frappe.query_report_filters_by_name.company.get_value(),
|
||||
"from_date": data.from_date || data.year_start_date,
|
||||
"to_date": data.to_date || data.year_end_date
|
||||
"to_date": data.to_date || data.year_end_date,
|
||||
"project": $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; })[0].$input.val()
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
|
@ -36,7 +36,7 @@ $.extend(erpnext.queries, {
|
||||
|
||||
customer_filter: function(doc) {
|
||||
if(!doc.customer) {
|
||||
frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, "customer", doc.name))));
|
||||
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "customer", doc.name))]));
|
||||
}
|
||||
|
||||
return { filters: { customer: doc.customer } };
|
||||
@ -45,8 +45,8 @@ $.extend(erpnext.queries, {
|
||||
contact_query: function(doc) {
|
||||
if(frappe.dynamic_link) {
|
||||
if(!doc[frappe.dynamic_link.fieldname]) {
|
||||
frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype,
|
||||
frappe.dynamic_link.fieldname, doc.name))));
|
||||
frappe.throw(__("Please set {0}",
|
||||
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
|
||||
}
|
||||
|
||||
return {
|
||||
@ -58,8 +58,8 @@ $.extend(erpnext.queries, {
|
||||
address_query: function(doc) {
|
||||
if(frappe.dynamic_link) {
|
||||
if(!doc[frappe.dynamic_link.fieldname]) {
|
||||
frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype,
|
||||
frappe.dynamic_link.fieldname, doc.name))));
|
||||
frappe.throw(__("Please set {0}",
|
||||
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
|
||||
}
|
||||
|
||||
return {
|
||||
@ -68,9 +68,16 @@ $.extend(erpnext.queries, {
|
||||
}
|
||||
},
|
||||
|
||||
company_address_query: function(doc) {
|
||||
return {
|
||||
query: 'frappe.geo.doctype.address.address.address_query',
|
||||
filters: { is_your_company_address: 1, link_doctype: 'Company', link_name: doc.company || '' }
|
||||
};
|
||||
},
|
||||
|
||||
supplier_filter: function(doc) {
|
||||
if(!doc.supplier) {
|
||||
frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, "supplier", doc.name))));
|
||||
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "supplier", doc.name))]));
|
||||
}
|
||||
|
||||
return { filters: { supplier: doc.supplier } };
|
||||
@ -78,8 +85,8 @@ $.extend(erpnext.queries, {
|
||||
|
||||
lead_filter: function(doc) {
|
||||
if(!doc.lead) {
|
||||
frappe.throw(__("Please specify a") + " " +
|
||||
__(frappe.meta.get_label(doc.doctype, "lead", doc.name)));
|
||||
frappe.throw(__("Please specify a {0}",
|
||||
[__(frappe.meta.get_label(doc.doctype, "lead", doc.name))]));
|
||||
}
|
||||
|
||||
return { filters: { lead: doc.lead } };
|
||||
|
@ -82,32 +82,6 @@ $.extend(erpnext, {
|
||||
|
||||
|
||||
$.extend(erpnext.utils, {
|
||||
clear_address_and_contact: function(frm) {
|
||||
$(frm.fields_dict['address_html'].wrapper).html("");
|
||||
frm.fields_dict['contact_html'] && $(frm.fields_dict['contact_html'].wrapper).html("");
|
||||
},
|
||||
|
||||
render_address_and_contact: function(frm) {
|
||||
// render address
|
||||
$(frm.fields_dict['address_html'].wrapper)
|
||||
.html(frappe.render_template("address_list",
|
||||
cur_frm.doc.__onload))
|
||||
.find(".btn-address").on("click", function() {
|
||||
frappe.new_doc("Address");
|
||||
});
|
||||
|
||||
// render contact
|
||||
if(frm.fields_dict['contact_html']) {
|
||||
$(frm.fields_dict['contact_html'].wrapper)
|
||||
.html(frappe.render_template("contact_list",
|
||||
cur_frm.doc.__onload))
|
||||
.find(".btn-contact").on("click", function() {
|
||||
frappe.new_doc("Contact");
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
set_party_dashboard_indicators: function(frm) {
|
||||
if(frm.doc.__onload && frm.doc.__onload.dashboard_info) {
|
||||
var info = frm.doc.__onload.dashboard_info;
|
||||
|
@ -1,9 +0,0 @@
|
||||
// Copyright (c) 2016, Frappe and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Announcement', {
|
||||
onload: function(frm) {
|
||||
frm.add_fetch('instructor', 'instructor_name' , 'posted_by');
|
||||
}
|
||||
});
|
||||
|
@ -1,315 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "announcement.#####",
|
||||
"beta": 0,
|
||||
"creation": "2016-06-23 05:37:33.996289",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "",
|
||||
"fieldname": "receiver",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Receiver",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Student\nStudent Group\nAll Students",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "instructor",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Instructor",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Instructor",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval: doc.receiver == \"Student\"",
|
||||
"fieldname": "student",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Student",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Student",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval: doc.receiver == \"Student Group\"",
|
||||
"fieldname": "student_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"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,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "posted_by",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Posted By",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "subject",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Subject",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Announcement",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 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": "2016-07-21 06:30:12.825629",
|
||||
"modified_by": "r@r.com",
|
||||
"module": "Schools",
|
||||
"name": "Announcement",
|
||||
"name_case": "",
|
||||
"owner": "demo@erpnext.com",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"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,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "subject",
|
||||
"track_seen": 1
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
class Announcement(Document):
|
||||
def validate(self):
|
||||
self.validate_receiver()
|
||||
self.set_posted_by()
|
||||
|
||||
def validate_receiver(self):
|
||||
if self.receiver == "Student":
|
||||
if not self.student:
|
||||
frappe.throw(_("Please select a Student"))
|
||||
self.student_group = None
|
||||
elif self.receiver == "Student Group":
|
||||
if not self.student_group:
|
||||
frappe.throw(_("Please select a Student Group"))
|
||||
self.student = None
|
||||
else:
|
||||
self.student_group = None
|
||||
self.student = None
|
||||
|
||||
def set_posted_by(self):
|
||||
if self.instructor:
|
||||
self.posted_by = frappe.db.get_value("Instructor", self.instructor, "instructor_name")
|
||||
else:
|
||||
self.posted_by = frappe.session.user
|
||||
|
||||
|
||||
|
||||
|
||||
def get_message_list(doctype, txt, filters, limit_start, limit_page_length=20):
|
||||
user = frappe.session.user
|
||||
student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
|
||||
if student:
|
||||
sg_list = frappe.db.sql("""select parent from `tabStudent Group Student` as sgs
|
||||
where sgs.student = %s """,(student))
|
||||
|
||||
data = frappe.db.sql("""select name, receiver, subject, description, posted_by, modified,
|
||||
student, student_group
|
||||
from `tabAnnouncement` as announce
|
||||
where (announce.receiver = "Student" and announce.student = %s)
|
||||
or (announce.receiver = "Student Group" and announce.student_group in %s)
|
||||
or announce.receiver = "All Students"
|
||||
and announce.docstatus = 1
|
||||
order by announce.idx asc limit {0} , {1}"""
|
||||
.format(limit_start, limit_page_length), (student,sg_list), as_dict = True)
|
||||
|
||||
for announcement in data:
|
||||
try:
|
||||
num_attachments = frappe.db.sql(""" select count(file_url) from tabFile as file
|
||||
where file.attached_to_name=%s
|
||||
and file.attached_to_doctype=%s""",(announcement.name,"Announcement"))
|
||||
|
||||
except IOError or frappe.DoesNotExistError:
|
||||
pass
|
||||
frappe.local.message_log.pop()
|
||||
|
||||
announcement.num_attachments = num_attachments[0][0]
|
||||
|
||||
return data
|
||||
|
||||
def get_list_context(context=None):
|
||||
return {
|
||||
"show_sidebar": True,
|
||||
'no_breadcrumbs': True,
|
||||
"title": _("Announcements"),
|
||||
"get_list": get_message_list,
|
||||
"row_template": "templates/includes/announcement/announcement_row.html"
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Announcement')
|
||||
|
||||
class TestAnnouncement(unittest.TestCase):
|
||||
pass
|
@ -13,7 +13,7 @@ class AssessmentPlan(Document):
|
||||
frappe.throw(_("Please select Student Group or Student Batch"))
|
||||
self.validate_student_batch()
|
||||
self.validate_overlap()
|
||||
|
||||
self.validate_max_score()
|
||||
|
||||
def validate_overlap(self):
|
||||
"""Validates overlap for Student Group/Student Batch, Instructor, Room"""
|
||||
@ -43,3 +43,10 @@ class AssessmentPlan(Document):
|
||||
def validate_student_batch(self):
|
||||
if self.student_group:
|
||||
self.student_batch = frappe.db.get_value("Student Group", self.student_group, "student_batch")
|
||||
|
||||
def validate_max_score(self):
|
||||
max_score = 0
|
||||
for d in self.evaluation_criterias:
|
||||
max_score += d.maximum_score
|
||||
if self.maximum_assessment_score != max_score:
|
||||
frappe.throw(_("Sum of Scores of Evaluation Criterias needs to be {0}.".format(self.maximum_assessment_score)))
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2016, Frappe and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Discussion', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -1,37 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Discussion(Document):
|
||||
def validate(self):
|
||||
if not self.owner== frappe.session.user:
|
||||
frappe.throw(_("Not Permitted"))
|
||||
|
||||
def get_discussions(doctype, txt, filters, limit_start, limit_page_length=20):
|
||||
from frappe.www.list import get_list
|
||||
if not filters:
|
||||
filters = []
|
||||
filters.append(("Discussion", "course", "=", frappe.form_dict.course))
|
||||
return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=True)
|
||||
|
||||
def get_list_context(context=None):
|
||||
course_name = frappe.form_dict.course
|
||||
portal_items = [{'reference_doctype': u'Topic', 'route': u"/topic?course=" + str(course_name), 'show_always': 0L, 'title': u'Topics'},
|
||||
{'reference_doctype': u'Discussion', 'route': u"/discussion?course=" + str(course_name), 'show_always': 0L, 'title': u'Discussions'},
|
||||
|
||||
]
|
||||
sidebar_title = course_name
|
||||
return {
|
||||
"show_sidebar": True,
|
||||
'no_breadcrumbs': True,
|
||||
"get_list" : get_discussions,
|
||||
"title": _("Discussions"),
|
||||
"sidebar_items" : portal_items,
|
||||
"sidebar_title" : sidebar_title,
|
||||
"row_template": "templates/includes/discussion/discussion_row.html"
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Discussion')
|
||||
|
||||
class TestDiscussion(unittest.TestCase):
|
||||
pass
|
@ -1,12 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Topic')
|
||||
|
||||
class TestTopic(unittest.TestCase):
|
||||
pass
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2016, Frappe and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Topic', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -1,49 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
class Topic(Document):
|
||||
pass
|
||||
|
||||
def get_topic_list(doctype, txt, filters, limit_start, limit_page_length=20):
|
||||
user = frappe.session.user
|
||||
student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
|
||||
if student:
|
||||
data = frappe. db.sql('''select name, course, modified,topic_name, introduction, content from `tabTopic` as topic
|
||||
where topic.course = %s
|
||||
order by idx asc limit {0} , {1}'''.format(limit_start, limit_page_length),filters.course,as_dict = True)
|
||||
|
||||
for topic in data:
|
||||
try:
|
||||
num_attachments = frappe.db.sql(""" select count(file_url) from tabFile as file
|
||||
where file.attached_to_name=%s
|
||||
and file.attached_to_doctype=%s""",(topic.name,"Topic"))
|
||||
|
||||
except IOError or frappe.DoesNotExistError:
|
||||
pass
|
||||
frappe.local.message_log.pop()
|
||||
|
||||
topic.num_attachments = num_attachments[0][0]
|
||||
|
||||
return data
|
||||
|
||||
def get_list_context(context=None):
|
||||
course = frappe.get_doc('Course', frappe.form_dict.course)
|
||||
portal_items = [{'reference_doctype': u'Topic', 'route': u"/topic?course=" + str(course.name), 'show_always': 0L, 'title': u'Topics'},
|
||||
{'reference_doctype': u'Discussion', 'route': u"/discussion?course=" + str(course.name), 'show_always': 0L, 'title': u'Discussions'},
|
||||
|
||||
]
|
||||
return {
|
||||
"show_sidebar": True,
|
||||
"title": _("Topic"),
|
||||
'no_breadcrumbs': True,
|
||||
"sidebar_items" : portal_items,
|
||||
"sidebar_title" : course.name,
|
||||
"get_list": get_topic_list,
|
||||
"row_template": "templates/includes/topic/topic_row.html"
|
||||
}
|
@ -61,7 +61,7 @@ def get_attendance_list(from_date, to_date, student_batch, students_list):
|
||||
students_with_leave_application = get_students_with_leave_application(from_date, to_date, students_list)
|
||||
for d in attendance_list:
|
||||
att_map.setdefault(d.student, frappe._dict()).setdefault(d.date, "")
|
||||
if students_with_leave_application and d.student in students_with_leave_application.get(d.date,[]):
|
||||
if students_with_leave_application and d.student in students_with_leave_application.get(d.date):
|
||||
att_map[d.student][d.date] = "Present"
|
||||
else:
|
||||
att_map[d.student][d.date] = d.status
|
||||
|
@ -37,7 +37,7 @@ frappe.ui.form.on("Customer", {
|
||||
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
||||
|
||||
if(!frm.doc.__islocal) {
|
||||
erpnext.utils.render_address_and_contact(frm);
|
||||
frappe.geo.render_address_and_contact(frm);
|
||||
|
||||
// custom buttons
|
||||
frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
@ -53,7 +53,7 @@ frappe.ui.form.on("Customer", {
|
||||
erpnext.utils.set_party_dashboard_indicators(frm);
|
||||
|
||||
} else {
|
||||
erpnext.utils.clear_address_and_contact(frm);
|
||||
frappe.geo.clear_address_and_contact(frm);
|
||||
}
|
||||
|
||||
var grid = cur_frm.get_field("sales_team").grid;
|
||||
|
@ -9,7 +9,7 @@ import frappe.defaults
|
||||
from frappe.utils import flt, cint, cstr
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact, delete_contact_and_address
|
||||
from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
|
||||
from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this
|
||||
from erpnext.accounts.party_status import get_party_status
|
||||
from erpnext import get_default_currency
|
||||
@ -95,9 +95,14 @@ class Customer(TransactionBase):
|
||||
def create_lead_address_contact(self):
|
||||
if self.lead_name:
|
||||
# assign lead address to customer (if already not set)
|
||||
address_name = frappe.get_value('Dynamic Link', dict(parenttype='Address', link_doctype='Lead', link_name=self.name))
|
||||
if address_name:
|
||||
address = frappe.get_doc('Address', address_name)
|
||||
address_names = frappe.get_all('Dynamic Link', filters={
|
||||
"parenttype":"Address",
|
||||
"link_doctype":"Lead",
|
||||
"link_name":self.lead_name
|
||||
}, fields=["parent as name"])
|
||||
|
||||
for address_name in address_names:
|
||||
address = frappe.get_doc('Address', address_name.get('name'))
|
||||
if not address.has_link('Customer', self.name):
|
||||
address.append('links', dict(link_doctype='Customer', link_name=self.name))
|
||||
address.save()
|
||||
@ -105,17 +110,17 @@ class Customer(TransactionBase):
|
||||
lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no"], as_dict=True)
|
||||
|
||||
# create contact from lead
|
||||
c = frappe.new_doc('Contact')
|
||||
c.first_name = lead.lead_name
|
||||
c.email_id = lead.email_id
|
||||
c.phone = lead.phone
|
||||
c.mobile_no = lead.mobile_no
|
||||
c.is_primary_contact = 1
|
||||
c.append('links', dict(link_doctype='Customer', link_name=self.name))
|
||||
c.flags.ignore_permissions = self.flags.ignore_permissions
|
||||
c.autoname()
|
||||
if not frappe.db.exists("Contact", c.name):
|
||||
c.insert()
|
||||
contact = frappe.new_doc('Contact')
|
||||
contact.first_name = lead.lead_name
|
||||
contact.email_id = lead.email_id
|
||||
contact.phone = lead.phone
|
||||
contact.mobile_no = lead.mobile_no
|
||||
contact.is_primary_contact = 1
|
||||
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
|
||||
contact.flags.ignore_permissions = self.flags.ignore_permissions
|
||||
contact.autoname()
|
||||
if not frappe.db.exists("Contact", contact.name):
|
||||
contact.insert()
|
||||
|
||||
def validate_name_with_customer_group(self):
|
||||
if frappe.db.exists("Customer Group", self.name):
|
||||
@ -133,7 +138,7 @@ class Customer(TransactionBase):
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Customer', self.name)
|
||||
if self.lead_name:
|
||||
frappe.db.sql("update `tabLead` set status='Interested' where name=%s",self.lead_name)
|
||||
frappe.db.sql("update `tabLead` set status='Interested' where name=%s", self.lead_name)
|
||||
|
||||
def after_rename(self, olddn, newdn, merge=False):
|
||||
if frappe.defaults.get_global_default('cust_master_name') == 'Customer Name':
|
||||
|
@ -12,9 +12,9 @@ def get_funnel_data(from_date, to_date):
|
||||
where (date(`modified`) between %s and %s)
|
||||
and status != "Do Not Contact" """, (from_date, to_date))[0][0]
|
||||
|
||||
active_leads += frappe.db.sql("""select count(distinct customer) from `tabContact`
|
||||
where (date(`modified`) between %s and %s)
|
||||
and status != "Passive" """, (from_date, to_date))[0][0]
|
||||
active_leads += frappe.db.sql("""select count(distinct contact.name) from `tabContact` contact
|
||||
left join `tabDynamic Link` dl on (dl.parent=contact.name) where dl.link_doctype='Customer'
|
||||
and (date(contact.modified) between %s and %s) and status != "Passive" """, (from_date, to_date))[0][0]
|
||||
|
||||
opportunities = frappe.db.sql("""select count(*) from `tabOpportunity`
|
||||
where (date(`creation`) between %s and %s)
|
||||
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2012-10-04 18:45:27",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-08-24 11:44:00.711112",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Customer Addresses And Contacts",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n\t`tabCustomer`.name as \"Customer ID:Link/Customer\",\n\t`tabCustomer`.customer_name as \"Customer Name\",\n\t`tabCustomer`.customer_group as \"Customer Group:Link/Customer Group\",\n\t`tabAddress`.address_line1 as \"Address Line 1\",\n\t`tabAddress`.address_line2 as \"Address Line 2\",\n\t`tabAddress`.city as \"City\",\n\t`tabAddress`.state as \"State\",\n\t`tabAddress`.pincode as \"Postal Code\",\n\t`tabAddress`.country as \"Country\",\n\t`tabAddress`.is_primary_address as \"Is Primary Address:Check\", \n\t`tabContact`.first_name as \"First Name\",\n\t`tabContact`.last_name as \"Last Name\",\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Address\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact:Check\"\nFROM\n\t`tabCustomer`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.customer=`tabCustomer`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.customer=`tabCustomer`.name\n\t)\nWHERE\n\t`tabCustomer`.docstatus<2\nORDER BY\n\t`tabCustomer`.name asc",
|
||||
"ref_doctype": "Customer",
|
||||
"report_name": "Customer Addresses And Contacts",
|
||||
"report_type": "Query Report"
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-10-22 11:58:16",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-02-02 11:39:57.231750",
|
||||
"modified": "2017-01-19 15:44:59.742195",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Lead Details",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Address::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.lead=`tabLead`.name\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
||||
"ref_doctype": "Lead",
|
||||
"report_name": "Lead Details",
|
||||
"report_type": "Query Report"
|
||||
|
@ -73,11 +73,23 @@ def delete_bins(company_name):
|
||||
|
||||
def delete_lead_addresses(company_name):
|
||||
"""Delete addresses to which leads are linked"""
|
||||
for lead in frappe.get_all("Lead", filters={"company": company_name}):
|
||||
frappe.db.sql("""delete from `tabAddress`
|
||||
where lead=%s and (customer='' or customer is null) and (supplier='' or supplier is null)""", lead.name)
|
||||
leads = frappe.get_all("Lead", filters={"company": company_name})
|
||||
leads = [ "'%s'"%row.get("name") for row in leads ]
|
||||
addresses = []
|
||||
if leads:
|
||||
addresses = frappe.db.sql_list("""select parent from `tabDynamic Link` where link_name
|
||||
in ({leads})""".format(leads=",".join(leads)), debug=True)
|
||||
addresses = ["'%s'"%addr for addr in addresses]
|
||||
|
||||
frappe.db.sql("""update `tabAddress` set lead=null, lead_name=null where lead=%s""", lead.name)
|
||||
frappe.db.sql("""delete from tabAddress where name in ({addresses}) and
|
||||
name not in (select distinct dl1.parent from `tabDynamic Link` dl1
|
||||
inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
|
||||
and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)), debug=True)
|
||||
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where link_doctype='Lead' and parenttype='Address'
|
||||
and link_name in ({leads})""".format(leads=",".join(leads)), debug=True)
|
||||
|
||||
frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)), debug=True)
|
||||
|
||||
def delete_communications(doctype, company_name, company_fieldname):
|
||||
frappe.db.sql("""
|
||||
|
@ -6,12 +6,12 @@ frappe.ui.form.on('Sales Partner', {
|
||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Sales Person'}
|
||||
|
||||
if(frm.doc.__islocal){
|
||||
hide_field(['address_html', 'contact_html']);
|
||||
erpnext.utils.clear_address_and_contact(frm);
|
||||
hide_field(['address_html', 'contact_html', 'address_contacts']);
|
||||
frappe.geo.clear_address_and_contact(frm);
|
||||
}
|
||||
else{
|
||||
unhide_field(['address_html', 'contact_html']);
|
||||
erpnext.utils.render_address_and_contact(frm);
|
||||
unhide_field(['address_html', 'contact_html', 'address_contacts']);
|
||||
frappe.geo.render_address_and_contact(frm);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cstr, filter_strip_join
|
||||
from frappe.website.website_generator import WebsiteGenerator
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from frappe.geo.address_and_contact import load_address_and_contact
|
||||
|
||||
class SalesPartner(WebsiteGenerator):
|
||||
website = frappe._dict(
|
||||
@ -28,15 +28,6 @@ class SalesPartner(WebsiteGenerator):
|
||||
if self.partner_website and not self.partner_website.startswith("http"):
|
||||
self.partner_website = "http://" + self.partner_website
|
||||
|
||||
def get_contacts(self, nm):
|
||||
if nm:
|
||||
return frappe.db.convert_to_lists(frappe.db.sql("""
|
||||
select name, CONCAT(IFNULL(first_name,''),
|
||||
' ',IFNULL(last_name,'')),contact_no,email_id
|
||||
from `tabContact` where sales_partner = %s""", nm))
|
||||
else:
|
||||
return ''
|
||||
|
||||
def get_context(self, context):
|
||||
address = frappe.db.get_value("Address",
|
||||
{"sales_partner": self.name, "is_primary_address": 1},
|
||||
|
@ -1,20 +0,0 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block header %}
|
||||
<h1> {{doc.subject}} </h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<p class="post-description"> {{doc.description}} </p>
|
||||
<p class="post-by text-muted small">
|
||||
{% for file in attached_files%}
|
||||
<a href="{{file.file_url}}" target="_new">{{file.file_name}}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
<br>
|
||||
<i>{{ doc.posted_by }}</i>
|
||||
<i class="blog-dot"></i> {{ frappe.format_date(doc.modified) }}
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
@ -1,18 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
announcement = frappe.get_doc('Announcement', frappe.form_dict.announcement)
|
||||
context.no_cache = 1
|
||||
context.show_sidebar = True
|
||||
announcement.has_permission('read')
|
||||
context.doc = announcement
|
||||
attachments = frappe.db.sql("""select file_url, file_name from tabFile as file
|
||||
where file.attached_to_name=%s """,(announcement.name), as_dict = True)
|
||||
|
||||
context.attached_files = attachments
|
||||
|
||||
|
@ -15,14 +15,6 @@ def get_context(context):
|
||||
course = frappe.get_doc('Course', frappe.form_dict.course)
|
||||
course.has_permission('read')
|
||||
context.doc = course
|
||||
portal_items = [{'reference_doctype': u'Topic', 'route': u"/topic?course=" + str(course.name), 'show_always': 0L, 'title': u'Topics'},
|
||||
{'reference_doctype': u'Discussion', 'route': u"/discussion?course=" + str(course.name), 'show_always': 0L, 'title': u'Discussions'},
|
||||
|
||||
]
|
||||
|
||||
context.sidebar_items = portal_items
|
||||
|
||||
context.sidebar_title = sidebar_title
|
||||
|
||||
context.intro = course.course_intro
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block header %}
|
||||
<h2> {{doc.subject}} </h2>
|
||||
<p> {{doc.description}} </p>
|
||||
<p class="text-muted small">Started by: {{doc.owner}} </p>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<div>
|
||||
{% include 'templates/includes/comments/comments.html' %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1,21 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.website.utils import get_comment_list
|
||||
|
||||
def get_context(context):
|
||||
context.doc = frappe.get_doc('Discussion', frappe.form_dict.discussion)
|
||||
portal_items = [{'reference_doctype': u'Topic', 'route': u"/topic?course=" + str(context.doc.course), 'show_always': 0L, 'title': u'Topics'},
|
||||
{'reference_doctype': u'Discussion', 'route': u"/discussion?course=" + str(context.doc.course), 'show_always': 0L, 'title': u'Discussions'},
|
||||
|
||||
]
|
||||
context.show_sidebar = True
|
||||
context.sidebar_items = portal_items
|
||||
context.no_cache = 1
|
||||
context.doc.has_permission('read')
|
||||
context.sidebar_title = context.doc.course
|
||||
context.reference_doctype = "Discussion"
|
||||
context.reference_name = context.doc.name
|
||||
context.comment_list = get_comment_list(context.doc.doctype,context.doc.name)
|
@ -1,12 +0,0 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
|
||||
{% block header %}
|
||||
<h2> {{ doc.introduction }} </h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<p class="post-description"> {{ doc.content }} </p>
|
||||
|
||||
{% endblock %}
|
@ -1,15 +0,0 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
topic = frappe.get_doc('Topic', frappe.form_dict.topic)
|
||||
context.no_cache = 1
|
||||
context.show_sidebar = True
|
||||
context.doc = topic
|
||||
attachments = frappe.db.sql("""select file_url, file_name from tabFile as file
|
||||
where file.attached_to_name=%s """,(topic.name), as_dict = True)
|
||||
|
||||
context.attached_files = attachments
|
@ -1,134 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def load_address_and_contact(doc, key):
|
||||
"""Loads address list and contact list in `__onload`"""
|
||||
from frappe.geo.doctype.address.address import get_address_display
|
||||
|
||||
address_list = [frappe.get_value('Address', a.parent, '*')
|
||||
for a in frappe.get_all('Dynamic Link', fields='parent',
|
||||
filters=dict(parenttype='Address', link_doctype=doc.doctype, link_name=doc.name))]
|
||||
|
||||
address_list = [a.update({"display": get_address_display(a)})
|
||||
for a in address_list]
|
||||
|
||||
address_list = sorted(address_list,
|
||||
lambda a, b:
|
||||
(int(a.is_primary_address - b.is_primary_address)) or
|
||||
(1 if a.modified - b.modified else 0))
|
||||
|
||||
doc.set_onload('addr_list', address_list)
|
||||
|
||||
if doc.doctype != "Lead":
|
||||
contact_list = [frappe.get_value('Contact', a.parent, '*')
|
||||
for a in frappe.get_all('Dynamic Link', fields='parent',
|
||||
filters=dict(parenttype='Contact', link_doctype=doc.doctype, link_name=doc.name))]
|
||||
|
||||
contact_list = sorted(contact_list,
|
||||
lambda a, b:
|
||||
(int(a.is_primary_contact - b.is_primary_contact)) or
|
||||
(1 if a.modified - b.modified else 0))
|
||||
|
||||
doc.set_onload('contact_list', contact_list)
|
||||
|
||||
def set_default_role(doc, method):
|
||||
'''Set customer, supplier, student based on email'''
|
||||
if frappe.flags.setting_role:
|
||||
return
|
||||
contact_name = frappe.get_value('Contact', dict(email_id=doc.email))
|
||||
if contact_name:
|
||||
contact = frappe.get_doc('Contact', contact_name)
|
||||
for link in contact.links:
|
||||
frappe.flags.setting_role = True
|
||||
if link.link_doctype=='Customer':
|
||||
doc.add_roles('Customer')
|
||||
elif link.link_doctype=='Supplier':
|
||||
doc.add_roles('Supplier')
|
||||
elif frappe.get_value('Student', dict(student_email_id=doc.email)):
|
||||
doc.add_roles('Student')
|
||||
|
||||
def has_permission(doc, ptype, user):
|
||||
links = get_permitted_and_not_permitted_links(doc.doctype)
|
||||
if not links.get("not_permitted_links"):
|
||||
# optimization: don't determine permissions based on link fields
|
||||
return True
|
||||
|
||||
# True if any one is True or all are empty
|
||||
names = []
|
||||
for df in (links.get("permitted_links") + links.get("not_permitted_links")):
|
||||
doctype = df.options
|
||||
name = doc.get(df.fieldname)
|
||||
names.append(name)
|
||||
|
||||
if name and frappe.has_permission(doctype, ptype, doc=name):
|
||||
return True
|
||||
|
||||
if not any(names):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_permission_query_conditions_for_contact(user):
|
||||
return get_permission_query_conditions("Contact")
|
||||
|
||||
def get_permission_query_conditions_for_address(user):
|
||||
return get_permission_query_conditions("Address")
|
||||
|
||||
def get_permission_query_conditions(doctype):
|
||||
links = get_permitted_and_not_permitted_links(doctype)
|
||||
|
||||
if not links.get("not_permitted_links"):
|
||||
# when everything is permitted, don't add additional condition
|
||||
return ""
|
||||
|
||||
elif not links.get("permitted_links"):
|
||||
conditions = []
|
||||
|
||||
# when everything is not permitted
|
||||
for df in links.get("not_permitted_links"):
|
||||
# like ifnull(customer, '')='' and ifnull(supplier, '')=''
|
||||
conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')=''".format(doctype=doctype, fieldname=df.fieldname))
|
||||
|
||||
return "( " + " and ".join(conditions) + " )"
|
||||
|
||||
else:
|
||||
conditions = []
|
||||
|
||||
for df in links.get("permitted_links"):
|
||||
# like ifnull(customer, '')!='' or ifnull(supplier, '')!=''
|
||||
conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname))
|
||||
|
||||
return "( " + " or ".join(conditions) + " )"
|
||||
|
||||
def get_permitted_and_not_permitted_links(doctype):
|
||||
permitted_links = []
|
||||
not_permitted_links = []
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
||||
for df in meta.get_link_fields():
|
||||
if df.options not in ("Customer", "Supplier", "Company", "Sales Partner"):
|
||||
continue
|
||||
|
||||
if frappe.has_permission(df.options):
|
||||
permitted_links.append(df)
|
||||
else:
|
||||
not_permitted_links.append(df)
|
||||
|
||||
return {
|
||||
"permitted_links": permitted_links,
|
||||
"not_permitted_links": not_permitted_links
|
||||
}
|
||||
|
||||
def delete_contact_and_address(doctype, name):
|
||||
for parenttype in ('Contact', 'Address'):
|
||||
items = frappe.db.sql("""select parent from `tabDynamic Link`
|
||||
where parenttype=%s and link_doctype=%s and link_name=%s""",
|
||||
(parenttype, doctype, name))
|
||||
|
||||
for name in items:
|
||||
doc = frappe.get_doc(parenttype, name)
|
||||
if len(doc.links)==1:
|
||||
doc.delete()
|
Loading…
Reference in New Issue
Block a user