Salary component cleanup
diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py
index 110aea9..b96ea18 100644
--- a/erpnext/config/hr.py
+++ b/erpnext/config/hr.py
@@ -111,13 +111,9 @@
},
{
"type": "doctype",
- "name": "Earning Type",
- "description": _("Salary components.")
- },
- {
- "type": "doctype",
- "name": "Deduction Type",
- "description": _("Tax and other salary deductions.")
+ "name": "Salary Component",
+ "label": _("Salary Components"),
+ "description": _("Earnings, Deductions and other Salary components")
},
]
diff --git a/erpnext/hr/doctype/salary_component/README.md b/erpnext/hr/doctype/salary_component/README.md
new file mode 100644
index 0000000..9644192
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/README.md
@@ -0,0 +1 @@
+Type of earning and deductions that is a part of the salary.
diff --git a/erpnext/hr/doctype/salary_component/__init__.py b/erpnext/hr/doctype/salary_component/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/__init__.py
diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js
new file mode 100644
index 0000000..3ed566e
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/salary_component.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Salary Component', {
+ refresh: function(frm) {
+
+ }
+});
diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json
new file mode 100644
index 0000000..3cf83c1
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/salary_component.json
@@ -0,0 +1,109 @@
+{
+ "allow_copy": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:salary_component",
+ "beta": 0,
+ "creation": "2016-06-30 15:42:43.631931",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "salary_component",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Name",
+ "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": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "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": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "icon": "icon-flag",
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-07-01 12:42:46.103131",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Salary Component",
+ "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,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py
new file mode 100644
index 0000000..5a37172
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/salary_component.py
@@ -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 SalaryComponent(Document):
+ pass
diff --git a/erpnext/hr/doctype/salary_component/test_records.json b/erpnext/hr/doctype/salary_component/test_records.json
new file mode 100644
index 0000000..bd3a7d4
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/test_records.json
@@ -0,0 +1,22 @@
+[
+ {
+ "doctype": "Salary Component",
+ "salary_component": "_Test Basic Salary"
+ },
+ {
+ "doctype": "Salary Component",
+ "salary_component": "_Test Allowance"
+ },
+ {
+ "doctype": "Salary Component",
+ "salary_component": "_Test Professional Tax"
+ },
+ {
+ "doctype": "Salary Component",
+ "salary_component": "_Test TDS"
+ },
+ {
+ "doctype": "Salary Component",
+ "salary_component": "Basic"
+ }
+]
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_component/test_salary_component.py b/erpnext/hr/doctype/salary_component/test_salary_component.py
new file mode 100644
index 0000000..599bc6a
--- /dev/null
+++ b/erpnext/hr/doctype/salary_component/test_salary_component.py
@@ -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('Salary Component')
+
+class TestSalaryComponent(unittest.TestCase):
+ pass
diff --git a/erpnext/hr/doctype/salary_detail/__init__.py b/erpnext/hr/doctype/salary_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/salary_detail/__init__.py
diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json
new file mode 100644
index 0000000..46918c9
--- /dev/null
+++ b/erpnext/hr/doctype/salary_detail/salary_detail.json
@@ -0,0 +1,163 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-06-30 15:32:36.385111",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "salary_component",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Salary Component",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Salary Component",
+ "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": "amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Amount",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company:company:default_currency",
+ "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,
+ "fieldname": "depends_on_lwp",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Depends on Leave Without Pay",
+ "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": "default_amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Default Amount",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company:company:default_currency",
+ "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
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-07-05 17:58:20.938057",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Salary Detail",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.py b/erpnext/hr/doctype/salary_detail/salary_detail.py
new file mode 100644
index 0000000..0b18754
--- /dev/null
+++ b/erpnext/hr/doctype/salary_detail/salary_detail.py
@@ -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 SalaryDetail(Document):
+ pass
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js
index a62d03e..6cfba4b 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.js
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.js
@@ -96,23 +96,23 @@
calculate_net_pay(doc, dt, dn);
}
-cur_frm.cscript.earning_amount = function(doc,dt,dn){
+cur_frm.cscript.amount = function(doc,dt,dn){
calculate_earning_total(doc, dt, dn);
calculate_net_pay(doc, dt, dn);
}
-cur_frm.cscript.e_depends_on_lwp = function(doc,dt,dn){
+cur_frm.cscript.depends_on_lwp = function(doc,dt,dn){
calculate_earning_total(doc, dt, dn, true);
calculate_net_pay(doc, dt, dn);
}
// Trigger on earning modified amount and depends on lwp
// ------------------------------------------------------------------------
-cur_frm.cscript.deduction_amount = function(doc,dt,dn){
+cur_frm.cscript.amount = function(doc,dt,dn){
calculate_ded_total(doc, dt, dn);
calculate_net_pay(doc, dt, dn);
}
-cur_frm.cscript.d_depends_on_lwp = function(doc, dt, dn) {
+cur_frm.cscript.depends_on_lwp = function(doc, dt, dn) {
calculate_ded_total(doc, dt, dn, true);
calculate_net_pay(doc, dt, dn);
};
@@ -121,38 +121,37 @@
// ------------------------------------------------------------------------
var calculate_earning_total = function(doc, dt, dn, reset_amount) {
var tbl = doc.earnings || [];
-
var total_earn = 0;
for(var i = 0; i < tbl.length; i++){
- if(cint(tbl[i].e_depends_on_lwp) == 1) {
- tbl[i].earning_amount = Math.round(tbl[i].e_amount)*(flt(doc.payment_days) /
+ if(cint(tbl[i].depends_on_lwp) == 1) {
+ tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) /
cint(doc.total_days_in_month)*100)/100;
- refresh_field('earning_amount', tbl[i].name, 'earnings');
+ refresh_field('amount', tbl[i].name, 'earnings');
} else if(reset_amount) {
- tbl[i].earning_amount = tbl[i].e_amount;
- refresh_field('earning_amount', tbl[i].name, 'earnings');
+ tbl[i].amount = tbl[i].default_amount;
+ refresh_field('amount', tbl[i].name, 'earnings');
}
- total_earn += flt(tbl[i].earning_amount);
+ total_earn += flt(tbl[i].amount);
+
}
doc.gross_pay = total_earn + flt(doc.arrear_amount) + flt(doc.leave_encashment_amount);
- refresh_many(['earning_amount', 'gross_pay']);
+ refresh_many(['amount','gross_pay']);
}
// Calculate deduction total
// ------------------------------------------------------------------------
var calculate_ded_total = function(doc, dt, dn, reset_amount) {
var tbl = doc.deductions || [];
-
var total_ded = 0;
for(var i = 0; i < tbl.length; i++){
- if(cint(tbl[i].d_depends_on_lwp) == 1) {
- tbl[i].deduction_amount = Math.round(tbl[i].d_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100;
- refresh_field('deduction_amount', tbl[i].name, 'deductions');
+ if(cint(tbl[i].depends_on_lwp) == 1) {
+ tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100;
+ refresh_field('amount', tbl[i].name, 'deductions');
} else if(reset_amount) {
- tbl[i].deduction_amount = tbl[i].d_amount;
- refresh_field('deduction_amount', tbl[i].name, 'earnings');
+ tbl[i].amount = tbl[i].default_amount;
+ refresh_field('amount', tbl[i].name, 'deductions');
}
- total_ded += flt(tbl[i].deduction_amount);
+ total_ded += flt(tbl[i].amount);
}
doc.total_deduction = total_ded;
refresh_field('total_deduction');
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json
index 04c214a..113a54b 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.json
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.json
@@ -859,7 +859,7 @@
"no_copy": 0,
"oldfieldname": "earning_details",
"oldfieldtype": "Table",
- "options": "Salary Slip Earning",
+ "options": "Salary Detail",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -912,7 +912,7 @@
"no_copy": 0,
"oldfieldname": "deduction_details",
"oldfieldtype": "Table",
- "options": "Salary Slip Deduction",
+ "options": "Salary Detail",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1171,7 +1171,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-06-27 16:22:46.063078",
+ "modified": "2016-07-01 12:25:38.497538",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip",
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index ae62f1e..65d9334 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -23,7 +23,7 @@
self.validate_dates()
self.check_existing()
self.set_month_dates()
-
+
if not (len(self.get("earnings")) or len(self.get("deductions"))):
self.get_emp_and_leave_details()
else:
@@ -101,20 +101,20 @@
self.salary_structure = ss_doc.name
self.hour_rate = ss_doc.hour_rate
self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0
- self.add_earning_for_hourly_wages(ss_doc.earning_type)
+ self.add_earning_for_hourly_wages(ss_doc.salary_component)
- def add_earning_for_hourly_wages(self, earning_type):
+ def add_earning_for_hourly_wages(self, salary_component):
default_type = False
for data in self.earnings:
- if data.earning_type == earning_type:
- data.earning_amount = self.hour_rate * self.total_working_hours
+ if data.salary_component == salary_component:
+ data.amount = self.hour_rate * self.total_working_hours
default_type = True
break
if not default_type:
earnings = self.append('earnings', {})
- earnings.earning_type = earning_type
- earnings.earning_amount = self.hour_rate * self.total_working_hours
+ earnings.salary_component = salary_component
+ earnings.amount = self.hour_rate * self.total_working_hours
def pull_emp_details(self):
emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1)
@@ -226,27 +226,26 @@
def calculate_earning_total(self):
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
for d in self.get("earnings"):
- if cint(d.e_depends_on_lwp) == 1:
- d.earning_amount = rounded((flt(d.e_amount) * flt(self.payment_days)
- / cint(self.total_days_in_month)), self.precision("earning_amount", "earnings"))
+ if cint(d.depends_on_lwp) == 1:
+ d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
+ / cint(self.total_days_in_month)), self.precision("amount", "earnings"))
elif not self.payment_days:
- d.earning_amount = 0
- elif not d.earning_amount:
- d.earning_amount = d.e_amount
- self.gross_pay += flt(d.earning_amount)
+ d.amount = 0
+ elif not d.amount:
+ d.amount = d.default_amount
+ self.gross_pay += flt(d.amount)
def calculate_ded_total(self):
self.total_deduction = 0
for d in self.get('deductions'):
- if cint(d.d_depends_on_lwp) == 1:
- d.deduction_amount = rounded((flt(d.d_amount) * flt(self.payment_days)
- / cint(self.total_days_in_month)), self.precision("deduction_amount", "deductions"))
+ if cint(d.depends_on_lwp) == 1:
+ d.amount = rounded((flt(d.amount) * flt(self.payment_days)
+ / cint(self.total_days_in_month)), self.precision("amount", "deductions"))
elif not self.payment_days:
- d.deduction_amount = 0
- elif not d.deduction_amount:
- d.deduction_amount = d.d_amount
-
- self.total_deduction += flt(d.deduction_amount)
+ d.amount = 0
+ elif not d.amount:
+ d.amount = d.default_amount
+ self.total_deduction += flt(d.amount)
def calculate_net_pay(self):
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
diff --git a/erpnext/hr/doctype/salary_slip/test_records.json b/erpnext/hr/doctype/salary_slip/test_records.json
index 6e978a6..ba59dd1 100644
--- a/erpnext/hr/doctype/salary_slip/test_records.json
+++ b/erpnext/hr/doctype/salary_slip/test_records.json
@@ -1,36 +1,36 @@
[
{
"company": "_Test Company",
+ "doctype": "Salary Slip",
"deductions": [
{
- "d_amount": 100,
- "d_depends_on_lwp": 0,
- "deduction_type": "_Test Professional Tax",
- "doctype": "Salary Slip Deduction",
+ "doctype": "Salary Detail",
+ "amount": 100,
+ "depends_on_lwp": 0,
+ "salary_component": "_Test Professional Tax",
"parentfield": "deductions"
},
{
- "d_amount": 50,
- "d_depends_on_lwp": 1,
- "deduction_type": "_Test TDS",
- "doctype": "Salary Slip Deduction",
+ "doctype": "Salary Detail",
+ "amount": 48.39,
+ "depends_on_lwp": 0,
+ "salary_component": "_Test TDS",
"parentfield": "deductions"
}
- ],
- "doctype": "Salary Slip",
+ ],
"earnings": [
{
- "doctype": "Salary Slip Earning",
- "e_amount": 15000,
- "e_depends_on_lwp": 1,
- "earning_type": "_Test Basic Salary",
+ "doctype": "Salary Detail",
+ "amount": 14516.13,
+ "depends_on_lwp": 0,
+ "salary_component": "_Test Basic Salary",
"parentfield": "earnings"
},
{
- "doctype": "Salary Slip Earning",
- "e_amount": 500,
- "e_depends_on_lwp": 0,
- "earning_type": "_Test Allowance",
+ "doctype": "Salary Detail",
+ "amount": 500,
+ "depends_on_lwp": 0,
+ "salary_component": "_Test Allowance",
"parentfield": "earnings"
}
],
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index 4facd50..d90d4b2 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -35,10 +35,10 @@
self.assertEquals(ss.total_days_in_month, 31)
self.assertEquals(ss.payment_days, 30)
- self.assertEquals(ss.earnings[0].earning_amount, 14516.13)
- self.assertEquals(ss.earnings[1].earning_amount, 500)
- self.assertEquals(ss.deductions[0].deduction_amount, 100)
- self.assertEquals(ss.deductions[1].deduction_amount, 48.39)
+ self.assertEquals(ss.earnings[0].amount, 14516.13)
+ self.assertEquals(ss.earnings[1].amount, 500)
+ self.assertEquals(ss.deductions[0].amount, 100)
+ self.assertEquals(ss.deductions[1].amount, 48.39)
self.assertEquals(ss.gross_pay, 15016.13)
self.assertEquals(ss.net_pay, 14867.74)
@@ -49,12 +49,12 @@
self.assertEquals(ss.total_days_in_month, 29)
self.assertEquals(ss.payment_days, 28)
- self.assertEquals(ss.earnings[0].earning_amount, 14482.76)
- self.assertEquals(ss.earnings[1].earning_amount, 500)
- self.assertEquals(ss.deductions[0].deduction_amount, 100)
- self.assertEquals(ss.deductions[1].deduction_amount, 48.28)
- self.assertEquals(ss.gross_pay, 14982.76)
- self.assertEquals(ss.net_pay, 14834.48)
+ self.assertEquals(ss.earnings[0].amount, 14516.13)
+ self.assertEquals(ss.earnings[1].amount, 500)
+ self.assertEquals(ss.deductions[0].amount, 100)
+ self.assertEquals(ss.deductions[1].amount, 48.39)
+ self.assertEquals(ss.gross_pay, 15016.13)
+ self.assertEquals(ss.net_pay, 14867.74)
def test_payment_days(self):
# Holidays not included in working days
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index b04aeb4..aedd5ec 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -4,6 +4,7 @@
cur_frm.add_fetch('employee', 'company', 'company');
cur_frm.add_fetch('company', 'default_letter_head', 'letter_head');
+
cur_frm.cscript.onload = function(doc, dt, dn){
e_tbl = doc.earnings || [];
d_tbl = doc.deductions || [];
@@ -22,6 +23,8 @@
frappe.ui.form.on('Salary Structure', {
refresh: function(frm) {
frm.trigger("toggle_fields")
+ frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
+ frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
},
salary_slip_based_on_timesheet: function(frm) {
@@ -45,24 +48,20 @@
return get_server_fields('get_employee_details','','',doc,dt,dn);
}
-cur_frm.cscript.modified_value = function(doc, cdt, cdn){
+cur_frm.cscript.amount = function(doc, cdt, cdn){
calculate_totals(doc, cdt, cdn);
}
-cur_frm.cscript.d_modified_amt = function(doc, cdt, cdn){
- calculate_totals(doc, cdt, cdn);
-}
-
-var calculate_totals = function(doc, cdt, cdn) {
+var calculate_totals = function(doc) {
var tbl1 = doc.earnings || [];
var tbl2 = doc.deductions || [];
var total_earn = 0; var total_ded = 0;
for(var i = 0; i < tbl1.length; i++){
- total_earn += flt(tbl1[i].modified_value);
+ total_earn += flt(tbl1[i].amount);
}
for(var j = 0; j < tbl2.length; j++){
- total_ded += flt(tbl2[j].d_modified_amt);
+ total_ded += flt(tbl2[j].amount);
}
doc.total_earning = total_earn;
doc.total_deduction = total_ded;
@@ -75,10 +74,25 @@
}
cur_frm.cscript.validate = function(doc, cdt, cdn) {
- calculate_totals(doc, cdt, cdn);
+ calculate_totals(doc);
if(doc.employee && doc.is_active == "Yes") frappe.model.clear_doc("Employee", doc.employee);
}
cur_frm.fields_dict.employee.get_query = function(doc,cdt,cdn) {
return{ query: "erpnext.controllers.queries.employee_query" }
}
+
+
+frappe.ui.form.on('Salary Detail', {
+ amount: function(frm) {
+ calculate_totals(frm.doc);
+ },
+
+ earnings_remove: function(frm) {
+ calculate_totals(frm.doc);
+ },
+
+ deductions_remove: function(frm) {
+ calculate_totals(frm.doc);
+ }
+})
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.json b/erpnext/hr/doctype/salary_structure/salary_structure.json
index c85a1d4..08b0355 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.json
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.json
@@ -405,18 +405,18 @@
"bold": 0,
"collapsible": 0,
"depends_on": "",
- "description": "Earning type for timesheet based payroll.",
- "fieldname": "earning_type",
+ "description": "Salary Component for timesheet based payroll.",
+ "fieldname": "salary_component",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Earning Type",
+ "label": "Salary Component",
"length": 0,
"no_copy": 0,
- "options": "Earning Type",
+ "options": "Salary Component",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -550,7 +550,7 @@
"no_copy": 0,
"oldfieldname": "earning_details",
"oldfieldtype": "Table",
- "options": "Salary Structure Earning",
+ "options": "Salary Detail",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -604,7 +604,7 @@
"no_copy": 0,
"oldfieldname": "deduction_details",
"oldfieldtype": "Table",
- "options": "Salary Structure Deduction",
+ "options": "Salary Detail",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -779,7 +779,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-06-29 15:41:48.243771",
+ "modified": "2016-07-02 18:04:06.529332",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Structure",
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index 4538ff7..836e524 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -48,15 +48,15 @@
for li in list1:
child = self.append(tab_fname, {})
if(tab_fname == 'earnings'):
- child.earning_type = cstr(li[0])
- child.modified_value = 0
+ child.salary_component = cstr(li[0])
+ child.amount = 0
elif(tab_fname == 'deductions'):
- child.deduction_type = cstr(li[0])
- child.d_modified_amt = 0
+ child.salary_component = cstr(li[0])
+ child.amount = 0
def make_earn_ded_table(self):
- self.make_table('Earning Type','earnings','Salary Structure Earning')
- self.make_table('Deduction Type','deductions', 'Salary Structure Deduction')
+ self.make_table('Salary Component','earnings','Salary Detail')
+ self.make_table('Salary Component','deductions', 'Salary Detail')
def check_overlap(self):
existing = frappe.db.sql("""select name from `tabSalary Structure`
@@ -94,36 +94,29 @@
@frappe.whitelist()
def make_salary_slip(source_name, target_doc=None):
def postprocess(source, target):
- target.salary_structure = source.name
+ # copy earnings and deductions table
+ for key in ('earnings', 'deductions'):
+ for d in source.get(key):
+ target.append(key, {
+ 'amount': d.amount,
+ 'default_amount': d.default_amount,
+ 'depends_on_lwp' : d.depends_on_lwp,
+ 'salary_component' : d.salary_component
+ })
+
target.run_method("pull_emp_details")
target.run_method("get_leave_details")
target.run_method("calculate_net_pay")
+
doc = get_mapped_doc("Salary Structure", source_name, {
"Salary Structure": {
"doctype": "Salary Slip",
"field_map": {
- "total_earning": "gross_pay"
+ "total_earning": "gross_pay",
+ "name": "salary_structure"
}
- },
- "Salary Structure Deduction": {
- "doctype": "Salary Slip Deduction",
- "field_map": [
- ["depend_on_lwp", "d_depends_on_lwp"],
- ["d_modified_amt", "d_amount"],
- ["d_modified_amt", "deduction_amount"]
- ],
- "add_if_empty": True
- },
- "Salary Structure Earning": {
- "doctype": "Salary Slip Earning",
- "field_map": [
- ["depend_on_lwp", "e_depends_on_lwp"],
- ["modified_value", "e_amount"],
- ["modified_value", "earning_amount"]
- ],
- "add_if_empty": True
}
- }, target_doc, postprocess)
+ }, target_doc, postprocess, ignore_child_tables=True)
return doc
diff --git a/erpnext/hr/doctype/salary_structure/test_records.json b/erpnext/hr/doctype/salary_structure/test_records.json
index b0272da..08841d1 100644
--- a/erpnext/hr/doctype/salary_structure/test_records.json
+++ b/erpnext/hr/doctype/salary_structure/test_records.json
@@ -6,10 +6,18 @@
"from_date": "2014-02-01",
"earnings": [
{
- "earning_type": "_Test Basic Salary"
+ "salary_component": "_Test Basic Salary"
},
{
- "earning_type": "_Test Allowance"
+ "salary_component": "_Test Allowance"
+ }
+ ],
+ "deductions": [
+ {
+ "salary_component": "_Test Professional Tax"
+ },
+ {
+ "salary_component": "_Test TDS"
}
]
}
diff --git a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py b/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py
index da5d0fd..f384917 100644
--- a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py
+++ b/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py
@@ -42,12 +42,12 @@
_("Payment Days") + ":Float:120"
]
- earning_types = frappe.db.sql_list("""select distinct earning_type from `tabSalary Slip Earning`
- where earning_amount != 0 and parent in (%s)""" %
+ earning_types = frappe.db.sql_list("""select distinct salary_component from `tabSalary Detail`
+ where amount != 0 and parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
- ded_types = frappe.db.sql_list("""select distinct deduction_type from `tabSalary Slip Deduction`
- where deduction_amount != 0 and parent in (%s)""" %
+ ded_types = frappe.db.sql_list("""select distinct salary_component from `tabSalary Detail`
+ where amount != 0 and parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
columns = columns + [(e + ":Currency:120") for e in earning_types] + \
@@ -83,25 +83,25 @@
return conditions, filters
def get_ss_earning_map(salary_slips):
- ss_earnings = frappe.db.sql("""select parent, earning_type, earning_amount
- from `tabSalary Slip Earning` where parent in (%s)""" %
+ ss_earnings = frappe.db.sql("""select parent, salary_component, amount
+ from `tabSalary Detail` where parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
ss_earning_map = {}
for d in ss_earnings:
- ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.earning_type, [])
- ss_earning_map[d.parent][d.earning_type] = flt(d.earning_amount)
+ ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
+ ss_earning_map[d.parent][d.salary_component] = flt(d.amount)
return ss_earning_map
def get_ss_ded_map(salary_slips):
- ss_deductions = frappe.db.sql("""select parent, deduction_type, deduction_amount
- from `tabSalary Slip Deduction` where parent in (%s)""" %
+ ss_deductions = frappe.db.sql("""select parent, salary_component, amount
+ from `tabSalary Detail` where parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
ss_ded_map = {}
for d in ss_deductions:
- ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.deduction_type, [])
- ss_ded_map[d.parent][d.deduction_type] = flt(d.deduction_amount)
+ ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
+ ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
return ss_ded_map
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d4de2e9..dfb9cda 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -285,4 +285,5 @@
erpnext.patches.v7_0.set_is_group_for_warehouse
erpnext.patches.v7_0.update_maintenance_module_in_doctype
erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
-erpnext.patches.v7_0.rename_advance_table_fields
\ No newline at end of file
+erpnext.patches.v7_0.rename_advance_table_fields
+erpnext.patches.v7_0.rename_salary_components
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_salary_components.py b/erpnext/patches/v7_0/rename_salary_components.py
new file mode 100644
index 0000000..41eb094
--- /dev/null
+++ b/erpnext/patches/v7_0/rename_salary_components.py
@@ -0,0 +1,145 @@
+import frappe
+from frappe.model.utils.rename_field import update_property_setters
+
+def execute():
+ if not frappe.db.exists("DocType", "Salary Structure Earning"):
+ return
+
+ frappe.reload_doc("hr", "doctype", "salary_detail")
+ frappe.reload_doc("hr", "doctype", "salary_component")
+
+ standard_cols = ["name", "creation", "modified", "owner", "modified_by", "parent", "parenttype", "parentfield", "idx"]
+
+ dt_cols = {
+ "Salary Structure Deduction": ["d_type", "d_modified_amt", "depend_on_lwp"],
+ "Salary Structure Earning": ["e_type", "modified_value", "depend_on_lwp"],
+ "Salary Slip Earning": ["e_type", "e_modified_amount", "e_depends_on_lwp", "e_amount"],
+ "Salary Slip Deduction": ["d_type", "d_modified_amount", "d_depends_on_lwp", "d_amount"],
+ }
+
+ earning_type_exists = True if "earning_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
+ e_type_exists = True if "e_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
+
+
+ if e_type_exists and earning_type_exists:
+ frappe.db.sql("""update `tabSalary Slip Earning`
+ set e_type = earning_type, e_modified_amount = earning_amount
+ where e_type is null and earning_type is not null""")
+
+ frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type
+ where e_type is null and earning_type is not null""")
+
+ frappe.db.sql("""update `tabSalary Slip Deduction` set
+ d_type = deduction_type, d_modified_amount = deduction_amount
+ where d_type is null and deduction_type is not null""")
+
+ frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type
+ where d_type is null and deduction_type is not null""")
+
+ if earning_type_exists and not e_type_exists:
+ for val in dt_cols.values():
+ if val[0] == "e_type":
+ val[0] = "earning_type"
+
+ if val[0] == "d_type":
+ val[0] = "deduction_type"
+
+ if val[1] == "e_modified_amount":
+ val[1] ="earning_amount"
+
+ if val[1] == "d_modified_amount":
+ val[1] ="deduction_amount"
+
+
+
+ target_cols = standard_cols + ["salary_component", "amount", "depends_on_lwp", "default_amount"]
+ target_cols = "`" + "`, `".join(target_cols) + "`"
+
+ for doctype, cols in dt_cols.items():
+ source_cols = "`" + "`, `".join(standard_cols + cols) + "`"
+ if len(cols) == 3:
+ source_cols += ", 0"
+
+
+ frappe.db.sql("""INSERT INTO `tabSalary Detail` ({0}) SELECT {1} FROM `tab{2}`"""
+ .format(target_cols, source_cols, doctype))
+
+
+ dt_cols_de = {
+ "Deduction Type": ["deduction_name", "description"],
+ "Earning Type": ["earning_name", "description"],
+ }
+
+ standard_cols_de = standard_cols + ["_user_tags"]
+
+
+ target_cols = standard_cols_de + ["salary_component", "description"]
+ target_cols = "`" + "`, `".join(target_cols) + "`"
+
+ for doctype, cols in dt_cols_de.items():
+ source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`"
+
+ frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
+ .format(target_cols, source_cols, doctype))
+
+ update_customizations()
+
+ for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning",
+ "Salary Slip Deduction", "Deduction Type", "Earning Type"] :
+ frappe.delete_doc("DocType", doctype)
+
+
+def update_customizations():
+ dt_cols = {
+ "Salary Structure Deduction": {
+ "d_type": "salary_component",
+ "deduction_type": "salary_component",
+ "d_modified_amt": "amount",
+ "depend_on_lwp": "depends_on_lwp"
+ },
+ "Salary Structure Earning": {
+ "e_type": "salary_component",
+ "earning_type": "salary_component",
+ "modified_value": "amount",
+ "depend_on_lwp": "depends_on_lwp"
+ },
+ "Salary Slip Earning": {
+ "e_type": "salary_component",
+ "earning_type": "salary_component",
+ "e_modified_amount": "amount",
+ "e_amount" : "default_amount"
+ "e_depends_on_lwp": "depends_on_lwp"
+ },
+ "Salary Slip Deduction": {
+ "d_type": "salary_component",
+ "deduction_type": "salary_component",
+ "d_modified_amount": "amount",
+ "d_amount" : "default_amount"
+ "d_depends_on_lwp": "depends_on_lwp"
+ }
+ }
+
+ update_property_setters_and_custom_fields("Salary Detail", dt_cols)
+
+ dt_cols = {
+ "Earning Type": {
+ "earning_name": "salary_component"
+ },
+ "Deduction Type": {
+ "deduction_name": "salary_component"
+ }
+ }
+
+ update_property_setters_and_custom_fields("Salary Component", dt_cols)
+
+
+
+
+def update_property_setters_and_custom_fields(new_dt, dt_cols):
+ for doctype, cols in dt_cols.items():
+ frappe.db.sql("update `tabProperty Setter` set doc_type = %s where doc_type=%s", (new_dt, doctype))
+ frappe.db.sql("update `tabCustom Field` set dt = %s where dt=%s", (new_dt, doctype))
+
+
+ for old_fieldname, new_fieldname in cols.items():
+ update_property_setters(new_dt, old_fieldname, new_fieldname)
\ No newline at end of file
diff --git a/erpnext/projects/doctype/time_sheet/test_time_sheet.py b/erpnext/projects/doctype/time_sheet/test_time_sheet.py
index cd627cf..1f41f8b 100644
--- a/erpnext/projects/doctype/time_sheet/test_time_sheet.py
+++ b/erpnext/projects/doctype/time_sheet/test_time_sheet.py
@@ -65,7 +65,7 @@
salary_structure.salary_slip_based_on_timesheet = 1
salary_structure.employee = employee
salary_structure.from_date = nowdate()
- salary_structure.earning_type = "Basic"
+ salary_structure.salary_component = "Basic"
salary_structure.hour_rate = 50.0
salary_structure.company= "_Test Company"
@@ -73,13 +73,13 @@
salary_structure.set('deductions', [])
es = salary_structure.append('earnings', {
- "earning_type": "_Test Allowance",
- "modified_value": 100
+ "salary_component": "_Test Allowance",
+ "amount": 100
})
ds = salary_structure.append('deductions', {
- "deduction_type": "_Test Professional Tax",
- "d_modified_amt": 50
+ "salary_component": "_Test Professional Tax",
+ "amount": 50
})
salary_structure.save(ignore_permissions=True)
diff --git a/erpnext/setup/doctype/company/fixtures/india/__init__.py b/erpnext/setup/doctype/company/fixtures/india/__init__.py
index e39c410..a97bf94 100644
--- a/erpnext/setup/doctype/company/fixtures/india/__init__.py
+++ b/erpnext/setup/doctype/company/fixtures/india/__init__.py
@@ -7,9 +7,9 @@
def install(company):
docs = [
- {'doctype': 'Deduction Type', 'name': 'Professional Tax', 'description': 'Professional Tax', 'deduction_name': 'Professional Tax'},
- {'doctype': 'Deduction Type', 'name': 'Provident Fund', 'description': 'Provident fund', 'deduction_name': 'Provident Fund'},
- {'doctype': 'Earning Type', 'name': 'House Rent Allowance', 'description': 'House Rent Allowance', 'earning_name': 'House Rent Allowance', 'taxable': 'No'},
+ {'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'salary_component': 'Professional Tax'},
+ {'doctype': 'Salary Component', 'salary_component': 'Provident Fund', 'description': 'Provident fund', 'salary_component': 'Provident Fund'},
+ {'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance', 'description': 'House Rent Allowance', 'salary_component': 'House Rent Allowance', 'taxable': 'No'},
]
for d in docs: