feat: Income tax slab (#21399)
* Feat: Multiple tax as per new taxation rule * patch:for multiple tax slab, fix: payroll and exemption validation * Test: Fixture * feat: income tax slab with other charges and tax exempted deduction components * fix: added missing init file * fix: Patch fixed * fix: Patch fixed * fix: test fixes * fix: validate duplicate exemption declaration * fix: payment entry test case Co-authored-by: Anurag Mishra <mishranaman123@gmail.com>
This commit is contained in:
parent
7e73473a65
commit
58ee6c1e08
@ -587,7 +587,9 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
frm.set_query("account_for_change_amount", function() {
|
||||
return {
|
||||
filters: {
|
||||
account_type: ['in', ["Cash", "Bank"]]
|
||||
account_type: ['in', ["Cash", "Bank"]],
|
||||
company: frm.doc.company,
|
||||
is_group: 0
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -668,7 +670,8 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
frm.fields_dict["loyalty_redemption_account"].get_query = function() {
|
||||
return {
|
||||
filters:{
|
||||
"company": frm.doc.company
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -677,7 +680,8 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
frm.fields_dict["loyalty_redemption_cost_center"].get_query = function() {
|
||||
return {
|
||||
filters:{
|
||||
"company": frm.doc.company
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Other Income', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
@ -0,0 +1,138 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "HR-INCOME-.######",
|
||||
"creation": "2020-03-18 15:04:40.767434",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"employee",
|
||||
"employee_name",
|
||||
"payroll_period",
|
||||
"column_break_3",
|
||||
"company",
|
||||
"source",
|
||||
"amount",
|
||||
"amended_from"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee",
|
||||
"options": "Employee",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "payroll_period",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Payroll Period",
|
||||
"options": "Payroll Period",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "source",
|
||||
"fieldtype": "Data",
|
||||
"label": "Source"
|
||||
},
|
||||
{
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Employee Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Employee Other Income",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-19 18:06:45.361830",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Other Income",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Employee",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, 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 EmployeeOtherIncome(Document):
|
||||
pass
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestEmployeeOtherIncome(unittest.TestCase):
|
||||
pass
|
@ -1,620 +1,180 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "HR-TAX-DEC-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 16:53:36.175504",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "HR-TAX-DEC-.YYYY.-.#####",
|
||||
"creation": "2018-04-13 16:53:36.175504",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"employee",
|
||||
"employee_name",
|
||||
"department",
|
||||
"column_break_2",
|
||||
"payroll_period",
|
||||
"company",
|
||||
"amended_from",
|
||||
"section_break_8",
|
||||
"declarations",
|
||||
"section_break_10",
|
||||
"total_declared_amount",
|
||||
"column_break_12",
|
||||
"total_exemption_amount"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee",
|
||||
"options": "Employee",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Employee Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.department",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Department",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Department",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "employee.department",
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"label": "Department",
|
||||
"options": "Department",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payroll_period",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payroll Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Payroll Period",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "payroll_period",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Payroll Period",
|
||||
"options": "Payroll Period",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.company",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "employee.company",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Employee Tax Exemption Declaration",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Employee Tax Exemption Declaration",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "declarations",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Declarations",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Tax Exemption Declaration Category",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "declarations",
|
||||
"fieldtype": "Table",
|
||||
"label": "Declarations",
|
||||
"options": "Employee Tax Exemption Declaration Category"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_declared_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Declared 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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "total_declared_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Declared Amount",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Exemption 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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_incomes_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Other Incomes",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "income_from_other_sources",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Income From Other Sources",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "total_exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Exemption Amount",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-05-11 16:13:50.472670",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Declaration",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-18 14:56:25.625717",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Declaration",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"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": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Employee",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Employee",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -8,31 +8,17 @@ from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, calculate_annual_eligible_hra_exemption
|
||||
|
||||
class DuplicateDeclarationError(frappe.ValidationError): pass
|
||||
from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, \
|
||||
calculate_annual_eligible_hra_exemption, validate_duplicate_exemption_for_payroll_period
|
||||
|
||||
class EmployeeTaxExemptionDeclaration(Document):
|
||||
def validate(self):
|
||||
validate_tax_declaration(self.declarations)
|
||||
self.validate_duplicate()
|
||||
validate_duplicate_exemption_for_payroll_period(self.doctype, self.name, self.payroll_period, self.employee)
|
||||
self.set_total_declared_amount()
|
||||
self.set_total_exemption_amount()
|
||||
self.calculate_hra_exemption()
|
||||
|
||||
def validate_duplicate(self):
|
||||
duplicate = frappe.db.get_value("Employee Tax Exemption Declaration",
|
||||
filters = {
|
||||
"employee": self.employee,
|
||||
"payroll_period": self.payroll_period,
|
||||
"name": ["!=", self.name],
|
||||
"docstatus": ["!=", 2]
|
||||
}
|
||||
)
|
||||
if duplicate:
|
||||
frappe.throw(_("Duplicate Tax Declaration of {0} for period {1}")
|
||||
.format(self.employee, self.payroll_period), DuplicateDeclarationError)
|
||||
|
||||
def set_total_declared_amount(self):
|
||||
self.total_declared_amount = 0.0
|
||||
for d in self.declarations:
|
||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import unittest
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
from erpnext.hr.doctype.employee_tax_exemption_declaration.employee_tax_exemption_declaration import DuplicateDeclarationError
|
||||
from erpnext.hr.utils import DuplicateDeclarationError
|
||||
|
||||
class TestEmployeeTaxExemptionDeclaration(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -21,8 +21,6 @@
|
||||
"total_actual_amount",
|
||||
"column_break_12",
|
||||
"exemption_amount",
|
||||
"other_incomes_section",
|
||||
"income_from_other_sources",
|
||||
"attachment_section",
|
||||
"attachments",
|
||||
"amended_from"
|
||||
@ -111,16 +109,6 @@
|
||||
"label": "Total Exemption Amount",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "other_incomes_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Other Incomes"
|
||||
},
|
||||
{
|
||||
"fieldname": "income_from_other_sources",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Income From Other Sources"
|
||||
},
|
||||
{
|
||||
"fieldname": "attachment_section",
|
||||
"fieldtype": "Section Break"
|
||||
@ -142,7 +130,7 @@
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-02 19:02:15.398486",
|
||||
"modified": "2020-03-18 14:55:51.420016",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Proof Submission",
|
||||
|
@ -7,7 +7,8 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, calculate_hra_exemption_for_period
|
||||
from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, \
|
||||
calculate_hra_exemption_for_period, validate_duplicate_exemption_for_payroll_period
|
||||
|
||||
class EmployeeTaxExemptionProofSubmission(Document):
|
||||
def validate(self):
|
||||
@ -15,6 +16,7 @@ class EmployeeTaxExemptionProofSubmission(Document):
|
||||
self.set_total_actual_amount()
|
||||
self.set_total_exemption_amount()
|
||||
self.calculate_hra_exemption()
|
||||
validate_duplicate_exemption_for_payroll_period(self.doctype, self.name, self.payroll_period, self.employee)
|
||||
|
||||
def set_total_actual_amount(self):
|
||||
self.total_actual_amount = flt(self.get("house_rent_payment_amount"))
|
||||
@ -32,4 +34,4 @@ class EmployeeTaxExemptionProofSubmission(Document):
|
||||
self.exemption_amount += hra_exemption["total_eligible_hra_exemption"]
|
||||
self.monthly_hra_exemption = hra_exemption["monthly_exemption"]
|
||||
self.monthly_house_rent = hra_exemption["monthly_house_rent"]
|
||||
self.total_eligible_hra_exemption = hra_exemption["total_eligible_hra_exemption"]
|
||||
self.total_eligible_hra_exemption = hra_exemption["total_eligible_hra_exemption"]
|
||||
|
0
erpnext/hr/doctype/income_tax_slab/__init__.py
Normal file
0
erpnext/hr/doctype/income_tax_slab/__init__.py
Normal file
6
erpnext/hr/doctype/income_tax_slab/income_tax_slab.js
Normal file
6
erpnext/hr/doctype/income_tax_slab/income_tax_slab.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Income Tax Slab', {
|
||||
|
||||
});
|
160
erpnext/hr/doctype/income_tax_slab/income_tax_slab.json
Normal file
160
erpnext/hr/doctype/income_tax_slab/income_tax_slab.json
Normal file
@ -0,0 +1,160 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "Prompt",
|
||||
"creation": "2020-03-17 16:50:35.564915",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"effective_from",
|
||||
"company",
|
||||
"column_break_3",
|
||||
"allow_tax_exemption",
|
||||
"standard_tax_exemption_amount",
|
||||
"disabled",
|
||||
"amended_from",
|
||||
"taxable_salary_slabs_section",
|
||||
"slabs",
|
||||
"taxes_and_charges_on_income_tax_section",
|
||||
"other_taxes_and_charges"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "effective_from",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Effective from",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If enabled, Tax Exemption Declaration will be considered for income tax calculation.",
|
||||
"fieldname": "allow_tax_exemption",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Tax Exemption"
|
||||
},
|
||||
{
|
||||
"fieldname": "taxable_salary_slabs_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Taxable Salary Slabs"
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Income Tax Slab",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "slabs",
|
||||
"fieldtype": "Table",
|
||||
"label": "Taxable Salary Slabs",
|
||||
"options": "Taxable Salary Slab",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"depends_on": "allow_tax_exemption",
|
||||
"fieldname": "standard_tax_exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Standard Tax Exemption Amount",
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "taxes_and_charges_on_income_tax_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Taxes and Charges on Income Tax"
|
||||
},
|
||||
{
|
||||
"fieldname": "other_taxes_and_charges",
|
||||
"fieldtype": "Table",
|
||||
"label": "Other Taxes and Charges",
|
||||
"options": "Income Tax Slab Other Charges"
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-24 12:28:36.805904",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Income Tax Slab",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Administrator",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
10
erpnext/hr/doctype/income_tax_slab/income_tax_slab.py
Normal file
10
erpnext/hr/doctype/income_tax_slab/income_tax_slab.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, 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 IncomeTaxSlab(Document):
|
||||
pass
|
10
erpnext/hr/doctype/income_tax_slab/test_income_tax_slab.py
Normal file
10
erpnext/hr/doctype/income_tax_slab/test_income_tax_slab.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestIncomeTaxSlab(unittest.TestCase):
|
||||
pass
|
@ -0,0 +1,75 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-04-24 11:46:59.041180",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"description",
|
||||
"column_break_2",
|
||||
"percent",
|
||||
"conditions_section",
|
||||
"min_taxable_income",
|
||||
"column_break_7",
|
||||
"max_taxable_income"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "min_taxable_income",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Min Taxable Income",
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"columns": 4,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "percent",
|
||||
"fieldtype": "Percent",
|
||||
"in_list_view": 1,
|
||||
"label": "Percent",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "conditions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Conditions"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "max_taxable_income",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Max Taxable Income",
|
||||
"options": "Company:company:default_currency"
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-24 13:27:43.598967",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Income Tax Slab Other Charges",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, 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 IncomeTaxSlabOtherCharges(Document):
|
||||
pass
|
@ -1,401 +1,102 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "Prompt",
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 15:18:53.698553",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "Prompt",
|
||||
"creation": "2018-04-13 15:18:53.698553",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"column_break_2",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"section_break_5",
|
||||
"periods"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Start 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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Start Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "End 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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "End Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payroll Periods",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 1,
|
||||
"label": "Payroll Periods"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "periods",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payroll Periods",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Payroll Period Date",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Taxable Salary Slabs",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxable_salary_slabs",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Taxable Salary Slabs",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Taxable Salary Slab",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "standard_tax_exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Standard Tax Exemption 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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "periods",
|
||||
"fieldtype": "Table",
|
||||
"label": "Payroll Periods",
|
||||
"options": "Payroll Period Date"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-04-26 01:45:03.160929",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Payroll Period",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-03-18 18:13:23.859980",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Payroll Period",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -45,8 +45,9 @@ class PayrollPeriod(Document):
|
||||
+ _(") for {0}").format(self.company)
|
||||
frappe.throw(msg)
|
||||
|
||||
def get_payroll_period_days(start_date, end_date, employee):
|
||||
company = frappe.db.get_value("Employee", employee, "company")
|
||||
def get_payroll_period_days(start_date, end_date, employee, company=None):
|
||||
if not company:
|
||||
company = frappe.db.get_value("Employee", employee, "company")
|
||||
payroll_period = frappe.db.sql("""
|
||||
select name, start_date, end_date
|
||||
from `tabPayroll Period`
|
||||
|
@ -1,264 +1,263 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:salary_component",
|
||||
"creation": "2016-06-30 15:42:43.631931",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"salary_component",
|
||||
"salary_component_abbr",
|
||||
"type",
|
||||
"description",
|
||||
"column_break_4",
|
||||
"is_payable",
|
||||
"depends_on_payment_days",
|
||||
"is_tax_applicable",
|
||||
"deduct_full_tax_on_selected_payroll_date",
|
||||
"round_to_the_nearest_integer",
|
||||
"statistical_component",
|
||||
"do_not_include_in_total",
|
||||
"disabled",
|
||||
"flexible_benefits",
|
||||
"is_flexible_benefit",
|
||||
"max_benefit_amount",
|
||||
"column_break_9",
|
||||
"pay_against_benefit_claim",
|
||||
"only_tax_impact",
|
||||
"create_separate_payment_entry_against_benefit_claim",
|
||||
"section_break_11",
|
||||
"variable_based_on_taxable_salary",
|
||||
"section_break_5",
|
||||
"accounts",
|
||||
"condition_and_formula",
|
||||
"condition",
|
||||
"amount",
|
||||
"amount_based_on_formula",
|
||||
"formula",
|
||||
"column_break_28",
|
||||
"help"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "salary_component",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Name",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "salary_component_abbr",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Abbr",
|
||||
"print_width": "120px",
|
||||
"reqd": 1,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Select",
|
||||
"in_standard_filter": 1,
|
||||
"label": "Type",
|
||||
"options": "Earning\nDeduction",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.type == \"Earning\"",
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Tax Applicable"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "is_payable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Payable"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "depends_on_payment_days",
|
||||
"fieldtype": "Check",
|
||||
"label": "Depends on Payment Days",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "do_not_include_in_total",
|
||||
"fieldtype": "Check",
|
||||
"label": "Do Not Include in Total"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "is_tax_applicable",
|
||||
"fieldname": "deduct_full_tax_on_selected_payroll_date",
|
||||
"fieldtype": "Check",
|
||||
"label": "Deduct Full Tax on Selected Payroll Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
|
||||
"fieldname": "statistical_component",
|
||||
"fieldtype": "Check",
|
||||
"label": "Statistical Component"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.type==\"Earning\" && doc.statistical_component!=1",
|
||||
"fieldname": "flexible_benefits",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Flexible Benefits"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_flexible_benefit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Flexible Benefit"
|
||||
},
|
||||
{
|
||||
"depends_on": "is_flexible_benefit",
|
||||
"fieldname": "max_benefit_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Max Benefit Amount (Yearly)"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "is_flexible_benefit",
|
||||
"fieldname": "pay_against_benefit_claim",
|
||||
"fieldtype": "Check",
|
||||
"label": "Pay Against Benefit Claim"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.create_separate_payment_entry_against_benefit_claim !=1",
|
||||
"fieldname": "only_tax_impact",
|
||||
"fieldtype": "Check",
|
||||
"label": "Only Tax Impact (Cannot Claim But Part of Taxable Income)"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.only_tax_impact !=1",
|
||||
"fieldname": "create_separate_payment_entry_against_benefit_claim",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Separate Payment Entry Against Benefit Claim"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.type=='Deduction'",
|
||||
"fieldname": "section_break_11",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "variable_based_on_taxable_salary",
|
||||
"fieldtype": "Check",
|
||||
"label": "Variable Based On Taxable Salary"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.statistical_component != 1",
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounts"
|
||||
},
|
||||
{
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "Accounts",
|
||||
"options": "Salary Component Account"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
|
||||
"fieldname": "condition_and_formula",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Condition and Formula"
|
||||
},
|
||||
{
|
||||
"fieldname": "condition",
|
||||
"fieldtype": "Code",
|
||||
"label": "Condition"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "amount_based_on_formula",
|
||||
"fieldtype": "Check",
|
||||
"label": "Amount based on formula"
|
||||
},
|
||||
{
|
||||
"depends_on": "amount_based_on_formula",
|
||||
"fieldname": "formula",
|
||||
"fieldtype": "Code",
|
||||
"label": "Formula"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.amount_based_on_formula!==1",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Amount"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_28",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Help",
|
||||
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "round_to_the_nearest_integer",
|
||||
"fieldtype": "Check",
|
||||
"label": "Round to the Nearest Integer"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-flag",
|
||||
"modified": "2019-06-05 11:34:14.231228",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Component",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Employee"
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:salary_component",
|
||||
"creation": "2016-06-30 15:42:43.631931",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"salary_component",
|
||||
"salary_component_abbr",
|
||||
"type",
|
||||
"description",
|
||||
"column_break_4",
|
||||
"depends_on_payment_days",
|
||||
"is_tax_applicable",
|
||||
"deduct_full_tax_on_selected_payroll_date",
|
||||
"variable_based_on_taxable_salary",
|
||||
"exempted_from_income_tax",
|
||||
"round_to_the_nearest_integer",
|
||||
"statistical_component",
|
||||
"do_not_include_in_total",
|
||||
"disabled",
|
||||
"flexible_benefits",
|
||||
"is_flexible_benefit",
|
||||
"max_benefit_amount",
|
||||
"column_break_9",
|
||||
"pay_against_benefit_claim",
|
||||
"only_tax_impact",
|
||||
"create_separate_payment_entry_against_benefit_claim",
|
||||
"section_break_5",
|
||||
"accounts",
|
||||
"condition_and_formula",
|
||||
"condition",
|
||||
"amount",
|
||||
"amount_based_on_formula",
|
||||
"formula",
|
||||
"column_break_28",
|
||||
"help"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "salary_component",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Name",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "salary_component_abbr",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Abbr",
|
||||
"print_width": "120px",
|
||||
"reqd": 1,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Select",
|
||||
"in_standard_filter": 1,
|
||||
"label": "Type",
|
||||
"options": "Earning\nDeduction",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.type == \"Earning\"",
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Tax Applicable"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "depends_on_payment_days",
|
||||
"fieldtype": "Check",
|
||||
"label": "Depends on Payment Days",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "do_not_include_in_total",
|
||||
"fieldtype": "Check",
|
||||
"label": "Do Not Include in Total"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.is_tax_applicable && doc.type=='Earning'",
|
||||
"fieldname": "deduct_full_tax_on_selected_payroll_date",
|
||||
"fieldtype": "Check",
|
||||
"label": "Deduct Full Tax on Selected Payroll Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
|
||||
"fieldname": "statistical_component",
|
||||
"fieldtype": "Check",
|
||||
"label": "Statistical Component"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.type==\"Earning\" && doc.statistical_component!=1",
|
||||
"fieldname": "flexible_benefits",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Flexible Benefits"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_flexible_benefit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Flexible Benefit"
|
||||
},
|
||||
{
|
||||
"depends_on": "is_flexible_benefit",
|
||||
"fieldname": "max_benefit_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Max Benefit Amount (Yearly)"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "is_flexible_benefit",
|
||||
"fieldname": "pay_against_benefit_claim",
|
||||
"fieldtype": "Check",
|
||||
"label": "Pay Against Benefit Claim"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.create_separate_payment_entry_against_benefit_claim !=1",
|
||||
"fieldname": "only_tax_impact",
|
||||
"fieldtype": "Check",
|
||||
"label": "Only Tax Impact (Cannot Claim But Part of Taxable Income)"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.only_tax_impact !=1",
|
||||
"fieldname": "create_separate_payment_entry_against_benefit_claim",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Separate Payment Entry Against Benefit Claim"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.type == \"Deduction\"",
|
||||
"fieldname": "variable_based_on_taxable_salary",
|
||||
"fieldtype": "Check",
|
||||
"label": "Variable Based On Taxable Salary"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.statistical_component != 1",
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounts"
|
||||
},
|
||||
{
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "Accounts",
|
||||
"options": "Salary Component Account"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
|
||||
"fieldname": "condition_and_formula",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Condition and Formula"
|
||||
},
|
||||
{
|
||||
"fieldname": "condition",
|
||||
"fieldtype": "Code",
|
||||
"label": "Condition"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "amount_based_on_formula",
|
||||
"fieldtype": "Check",
|
||||
"label": "Amount based on formula"
|
||||
},
|
||||
{
|
||||
"depends_on": "amount_based_on_formula",
|
||||
"fieldname": "formula",
|
||||
"fieldtype": "Code",
|
||||
"label": "Formula"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.amount_based_on_formula!==1",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Amount"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_28",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Help",
|
||||
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "round_to_the_nearest_integer",
|
||||
"fieldtype": "Check",
|
||||
"label": "Round to the Nearest Integer"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.type == \"Deduction\" && !doc.variable_based_on_taxable_salary",
|
||||
"description": "If checked, the full amount will be deducted from taxable income before calculating income tax. Otherwise, it can be exempted via Employee Tax Exemption Declaration.",
|
||||
"fieldname": "exempted_from_income_tax",
|
||||
"fieldtype": "Check",
|
||||
"label": "Exempted from Income Tax"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-flag",
|
||||
"links": [],
|
||||
"modified": "2020-04-24 14:50:28.994054",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Component",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Employee"
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -3,14 +3,12 @@
|
||||
"doctype": "Salary Component",
|
||||
"salary_component": "_Test Basic Salary",
|
||||
"type": "Earning",
|
||||
"is_payable": 1,
|
||||
"is_tax_applicable": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Salary Component",
|
||||
"salary_component": "_Test Allowance",
|
||||
"type": "Earning",
|
||||
"is_payable": 1,
|
||||
"is_tax_applicable": 1
|
||||
},
|
||||
{
|
||||
@ -27,14 +25,12 @@
|
||||
"doctype": "Salary Component",
|
||||
"salary_component": "Basic",
|
||||
"type": "Earning",
|
||||
"is_payable": 1,
|
||||
"is_tax_applicable": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Salary Component",
|
||||
"salary_component": "Leave Encashment",
|
||||
"type": "Earning",
|
||||
"is_payable": 1,
|
||||
"is_tax_applicable": 1
|
||||
}
|
||||
]
|
@ -18,6 +18,5 @@ def create_salary_component(component_name, **args):
|
||||
"doctype": "Salary Component",
|
||||
"salary_component": component_name,
|
||||
"type": args.get("type") or "Earning",
|
||||
"is_payable": args.get("is_payable") or 1,
|
||||
"is_tax_applicable": args.get("is_tax_applicable") or 1
|
||||
}).insert()
|
||||
|
@ -12,6 +12,7 @@
|
||||
"deduct_full_tax_on_selected_payroll_date",
|
||||
"depends_on_payment_days",
|
||||
"is_tax_applicable",
|
||||
"exempted_from_income_tax",
|
||||
"is_flexible_benefit",
|
||||
"variable_based_on_taxable_salary",
|
||||
"section_break_2",
|
||||
@ -62,6 +63,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.parentfield=='earnings'",
|
||||
"fetch_from": "salary_component.is_tax_applicable",
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
@ -71,6 +73,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.parentfield=='earnings'",
|
||||
"fetch_from": "salary_component.is_flexible_benefit",
|
||||
"fieldname": "is_flexible_benefit",
|
||||
"fieldtype": "Check",
|
||||
@ -80,6 +83,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.parentfield=='deductions'",
|
||||
"fetch_from": "salary_component.variable_based_on_taxable_salary",
|
||||
"fieldname": "variable_based_on_taxable_salary",
|
||||
"fieldtype": "Check",
|
||||
@ -187,11 +191,20 @@
|
||||
"fieldtype": "HTML",
|
||||
"label": "Condition and Formula Help",
|
||||
"options": "<h3>Condition and Formula Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.parentfield=='deductions'",
|
||||
"fetch_from": "salary_component.exempted_from_income_tax",
|
||||
"fieldname": "exempted_from_income_tax",
|
||||
"fieldtype": "Check",
|
||||
"label": "Exempted from Income Tax",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-31 17:15:25.646689",
|
||||
"modified": "2020-04-24 20:00:16.475295",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Detail",
|
||||
|
@ -451,7 +451,8 @@ class SalarySlip(TransactionBase):
|
||||
'is_flexible_benefit': struct_row.is_flexible_benefit,
|
||||
'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary,
|
||||
'deduct_full_tax_on_selected_payroll_date': struct_row.deduct_full_tax_on_selected_payroll_date,
|
||||
'additional_amount': amount if struct_row.get("is_additional_component") else 0
|
||||
'additional_amount': amount if struct_row.get("is_additional_component") else 0,
|
||||
'exempted_from_income_tax': struct_row.exempted_from_income_tax
|
||||
})
|
||||
else:
|
||||
if struct_row.get("is_additional_component"):
|
||||
@ -482,10 +483,12 @@ class SalarySlip(TransactionBase):
|
||||
return self.calculate_variable_tax(payroll_period, tax_component)
|
||||
|
||||
def calculate_variable_tax(self, payroll_period, tax_component):
|
||||
# get Tax slab from salary structure assignment for the employee and payroll period
|
||||
tax_slab = self.get_income_tax_slabs(payroll_period)
|
||||
|
||||
# get remaining numbers of sub-period (period for which one salary is processed)
|
||||
remaining_sub_periods = get_period_factor(self.employee,
|
||||
self.start_date, self.end_date, self.payroll_frequency, payroll_period)[1]
|
||||
|
||||
# get taxable_earnings, paid_taxes for previous period
|
||||
previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date, self.start_date)
|
||||
previous_total_paid_taxes = self.get_tax_paid_in_period(payroll_period.start_date, self.start_date, tax_component)
|
||||
@ -507,23 +510,27 @@ class SalarySlip(TransactionBase):
|
||||
unclaimed_taxable_benefits += current_taxable_earnings_for_payment_days.flexi_benefits
|
||||
|
||||
# Total exemption amount based on tax exemption declaration
|
||||
total_exemption_amount, other_incomes = self.get_total_exemption_amount_and_other_incomes(payroll_period)
|
||||
total_exemption_amount = self.get_total_exemption_amount(payroll_period, tax_slab)
|
||||
|
||||
#Employee Other Incomes
|
||||
other_incomes = self.get_income_form_other_sources(payroll_period) or 0.0
|
||||
|
||||
# Total taxable earnings including additional and other incomes
|
||||
total_taxable_earnings = previous_taxable_earnings + current_structured_taxable_earnings + future_structured_taxable_earnings \
|
||||
+ current_additional_earnings + other_incomes + unclaimed_taxable_benefits - total_exemption_amount
|
||||
|
||||
|
||||
# Total taxable earnings without additional earnings with full tax
|
||||
total_taxable_earnings_without_full_tax_addl_components = total_taxable_earnings - current_additional_earnings_with_full_tax
|
||||
|
||||
# Structured tax amount
|
||||
total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components)
|
||||
total_structured_tax_amount = self.calculate_tax_by_tax_slab(
|
||||
total_taxable_earnings_without_full_tax_addl_components, tax_slab)
|
||||
current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods
|
||||
|
||||
|
||||
# Total taxable earnings with additional earnings with full tax
|
||||
full_tax_on_additional_earnings = 0.0
|
||||
if current_additional_earnings_with_full_tax:
|
||||
total_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings)
|
||||
total_tax_amount = self.calculate_tax_by_tax_slab(total_taxable_earnings, tax_slab)
|
||||
full_tax_on_additional_earnings = total_tax_amount - total_structured_tax_amount
|
||||
|
||||
current_tax_amount = current_structured_tax_amount + full_tax_on_additional_earnings
|
||||
@ -532,12 +539,30 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
return current_tax_amount
|
||||
|
||||
def get_income_tax_slabs(self, payroll_period):
|
||||
income_tax_slab, ss_assignment_name = frappe.db.get_value("Salary Structure Assignment",
|
||||
{"employee": self.employee, "salary_structure": self.salary_structure, "docstatus": 1}, ["income_tax_slab", 'name'])
|
||||
|
||||
if not income_tax_slab:
|
||||
frappe.throw(_("Income Tax Slab not set in Salary Structure Assignment: {0}").format(ss_assignment_name))
|
||||
|
||||
income_tax_slab_doc = frappe.get_doc("Income Tax Slab", income_tax_slab)
|
||||
if income_tax_slab_doc.disabled:
|
||||
frappe.throw(_("Income Tax Slab: {0} is disabled").format(income_tax_slab))
|
||||
|
||||
if getdate(income_tax_slab_doc.effective_from) > getdate(payroll_period.start_date):
|
||||
frappe.throw(_("Income Tax Slab must be effective on or before Payroll Period Start Date: {0}")
|
||||
.format(payroll_period.start_date))
|
||||
|
||||
return income_tax_slab_doc
|
||||
|
||||
|
||||
def get_taxable_earnings_for_prev_period(self, start_date, end_date):
|
||||
taxable_earnings = frappe.db.sql("""
|
||||
select sum(sd.amount)
|
||||
from
|
||||
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
|
||||
where
|
||||
where
|
||||
sd.parentfield='earnings'
|
||||
and sd.is_tax_applicable=1
|
||||
and is_flexible_benefit=0
|
||||
@ -550,7 +575,28 @@ class SalarySlip(TransactionBase):
|
||||
"from_date": start_date,
|
||||
"to_date": end_date
|
||||
})
|
||||
return flt(taxable_earnings[0][0]) if taxable_earnings else 0
|
||||
taxable_earnings = flt(taxable_earnings[0][0]) if taxable_earnings else 0
|
||||
|
||||
exempted_amount = frappe.db.sql("""
|
||||
select sum(sd.amount)
|
||||
from
|
||||
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
|
||||
where
|
||||
sd.parentfield='deductions'
|
||||
and sd.exempted_from_income_tax=1
|
||||
and is_flexible_benefit=0
|
||||
and ss.docstatus=1
|
||||
and ss.employee=%(employee)s
|
||||
and ss.start_date between %(from_date)s and %(to_date)s
|
||||
and ss.end_date between %(from_date)s and %(to_date)s
|
||||
""", {
|
||||
"employee": self.employee,
|
||||
"from_date": start_date,
|
||||
"to_date": end_date
|
||||
})
|
||||
exempted_amount = flt(exempted_amount[0][0]) if exempted_amount else 0
|
||||
|
||||
return taxable_earnings - exempted_amount
|
||||
|
||||
def get_tax_paid_in_period(self, start_date, end_date, tax_component):
|
||||
# find total_tax_paid, tax paid for benefit, additional_salary
|
||||
@ -610,6 +656,13 @@ class SalarySlip(TransactionBase):
|
||||
else:
|
||||
taxable_earnings += amount
|
||||
|
||||
for ded in self.deductions:
|
||||
if ded.exempted_from_income_tax:
|
||||
amount = ded.amount
|
||||
if based_on_payment_days:
|
||||
amount = self.get_amount_based_on_payment_days(ded, joining_date, relieving_date)[0]
|
||||
taxable_earnings -= flt(amount)
|
||||
|
||||
return frappe._dict({
|
||||
"taxable_earnings": taxable_earnings,
|
||||
"additional_income": additional_income,
|
||||
@ -672,40 +725,63 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
return total_benefits_paid - total_benefits_claimed
|
||||
|
||||
def get_total_exemption_amount_and_other_incomes(self, payroll_period):
|
||||
total_exemption_amount, other_incomes = 0, 0
|
||||
if self.deduct_tax_for_unsubmitted_tax_exemption_proof:
|
||||
exemption_proof = frappe.db.get_value("Employee Tax Exemption Proof Submission",
|
||||
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
|
||||
["exemption_amount", "income_from_other_sources"])
|
||||
if exemption_proof:
|
||||
total_exemption_amount, other_incomes = exemption_proof
|
||||
else:
|
||||
declaration = frappe.db.get_value("Employee Tax Exemption Declaration",
|
||||
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
|
||||
["total_exemption_amount", "income_from_other_sources"])
|
||||
if declaration:
|
||||
total_exemption_amount, other_incomes = declaration
|
||||
def get_total_exemption_amount(self, payroll_period, tax_slab):
|
||||
total_exemption_amount = 0
|
||||
if tax_slab.allow_tax_exemption:
|
||||
if self.deduct_tax_for_unsubmitted_tax_exemption_proof:
|
||||
exemption_proof = frappe.db.get_value("Employee Tax Exemption Proof Submission",
|
||||
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
|
||||
["exemption_amount"])
|
||||
if exemption_proof:
|
||||
total_exemption_amount = exemption_proof
|
||||
else:
|
||||
declaration = frappe.db.get_value("Employee Tax Exemption Declaration",
|
||||
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
|
||||
["total_exemption_amount"])
|
||||
if declaration:
|
||||
total_exemption_amount = declaration
|
||||
|
||||
return total_exemption_amount, other_incomes
|
||||
total_exemption_amount += flt(tax_slab.standard_tax_exemption_amount)
|
||||
|
||||
def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning):
|
||||
payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
|
||||
annual_taxable_earning -= flt(payroll_period_obj.standard_tax_exemption_amount)
|
||||
return total_exemption_amount
|
||||
|
||||
def get_income_form_other_sources(self, payroll_period):
|
||||
return frappe.get_all("Employee Other Income",
|
||||
filters={
|
||||
"employee": self.employee,
|
||||
"payroll_period": payroll_period.name,
|
||||
"company": self.company,
|
||||
"docstatus": 1
|
||||
},
|
||||
fields="SUM(amount) as total_amount"
|
||||
)[0].total_amount
|
||||
|
||||
def calculate_tax_by_tax_slab(self, annual_taxable_earning, tax_slab):
|
||||
data = self.get_data_for_eval()
|
||||
data.update({"annual_taxable_earning": annual_taxable_earning})
|
||||
taxable_amount = 0
|
||||
for slab in payroll_period_obj.taxable_salary_slabs:
|
||||
tax_amount = 0
|
||||
for slab in tax_slab.slabs:
|
||||
if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
|
||||
continue
|
||||
if not slab.to_amount and annual_taxable_earning > slab.from_amount:
|
||||
taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
||||
tax_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
||||
continue
|
||||
if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount:
|
||||
taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
||||
tax_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
|
||||
elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount:
|
||||
taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
|
||||
return taxable_amount
|
||||
tax_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
|
||||
|
||||
# other taxes and charges on income tax
|
||||
for d in tax_slab.other_taxes_and_charges:
|
||||
if flt(d.min_taxable_income) and flt(d.min_taxable_income) > tax_amount:
|
||||
continue
|
||||
|
||||
if flt(d.max_taxable_income) and flt(d.max_taxable_income) < tax_amount:
|
||||
continue
|
||||
|
||||
tax_amount += tax_amount * flt(d.percent) / 100
|
||||
|
||||
return tax_amount
|
||||
|
||||
def eval_tax_slab_condition(self, condition, data):
|
||||
try:
|
||||
|
@ -47,10 +47,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
self.assertEqual(ss.payment_days, no_of_days[0])
|
||||
self.assertEqual(ss.earnings[0].amount, 50000)
|
||||
self.assertEqual(ss.earnings[1].amount, 3000)
|
||||
self.assertEqual(ss.deductions[0].amount, 5000)
|
||||
self.assertEqual(ss.deductions[1].amount, 5000)
|
||||
self.assertEqual(ss.gross_pay, 78000)
|
||||
self.assertEqual(ss.net_pay, 68000.0)
|
||||
|
||||
def test_salary_slip_with_holidays_excluded(self):
|
||||
no_of_days = self.get_no_of_days()
|
||||
@ -67,10 +64,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
self.assertEqual(ss.earnings[0].amount, 50000)
|
||||
self.assertEqual(ss.earnings[0].default_amount, 50000)
|
||||
self.assertEqual(ss.earnings[1].amount, 3000)
|
||||
self.assertEqual(ss.deductions[0].amount, 5000)
|
||||
self.assertEqual(ss.deductions[1].amount, 5000)
|
||||
self.assertEqual(ss.gross_pay, 78000)
|
||||
self.assertEqual(ss.net_pay, 68000.0)
|
||||
|
||||
def test_payment_days(self):
|
||||
no_of_days = self.get_no_of_days()
|
||||
@ -80,8 +74,8 @@ class TestSalarySlip(unittest.TestCase):
|
||||
# set joinng date in the same month
|
||||
make_employee("test_employee@salary.com")
|
||||
if getdate(nowdate()).day >= 15:
|
||||
date_of_joining = getdate(add_days(nowdate(),-10))
|
||||
relieving_date = getdate(add_days(nowdate(),-10))
|
||||
date_of_joining = getdate(add_days(nowdate(),-10))
|
||||
elif getdate(nowdate()).day < 15 and getdate(nowdate()).day >= 5:
|
||||
date_of_joining = getdate(add_days(nowdate(),-3))
|
||||
relieving_date = getdate(add_days(nowdate(),-3))
|
||||
@ -131,9 +125,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
def test_email_salary_slip(self):
|
||||
frappe.db.sql("delete from `tabEmail Queue`")
|
||||
|
||||
hr_settings = frappe.get_doc("HR Settings", "HR Settings")
|
||||
hr_settings.email_salary_slip_to_employee = 1
|
||||
hr_settings.save()
|
||||
frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 1)
|
||||
|
||||
make_employee("test_employee@salary.com")
|
||||
ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
|
||||
@ -203,8 +195,11 @@ class TestSalarySlip(unittest.TestCase):
|
||||
# as per assigned salary structure 40500 in monthly salary so 236000*5/100/12
|
||||
frappe.db.sql("""delete from `tabPayroll Period`""")
|
||||
frappe.db.sql("""delete from `tabSalary Component`""")
|
||||
|
||||
payroll_period = create_payroll_period()
|
||||
create_tax_slab(payroll_period)
|
||||
|
||||
create_tax_slab(payroll_period, allow_tax_exemption=True)
|
||||
|
||||
employee = make_employee("test_tax@salary.slip")
|
||||
delete_docs = [
|
||||
"Salary Slip",
|
||||
@ -230,8 +225,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
payroll_period, deduct_random=False)
|
||||
tax_paid = get_tax_paid_in_period(employee)
|
||||
|
||||
# total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200
|
||||
annual_tax = 113568
|
||||
annual_tax = 113589.0
|
||||
try:
|
||||
self.assertEqual(tax_paid, annual_tax)
|
||||
except AssertionError:
|
||||
@ -255,8 +249,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
raise
|
||||
|
||||
# Submit proof for total 120000
|
||||
data["proof-1"] = create_proof_submission(employee, payroll_period, 50000)
|
||||
data["proof-2"] = create_proof_submission(employee, payroll_period, 70000)
|
||||
data["proof"] = create_proof_submission(employee, payroll_period, 120000)
|
||||
|
||||
# Submit benefit claim for total 50000
|
||||
data["benefit-1"] = create_benefit_claim(employee, payroll_period, 15000, "Medical Allowance")
|
||||
@ -270,7 +263,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
# total taxable income 416000, 166000 @ 5% ie. 8300
|
||||
try:
|
||||
self.assertEqual(tax_paid, 88608)
|
||||
self.assertEqual(tax_paid, 82389.0)
|
||||
except AssertionError:
|
||||
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
|
||||
raise
|
||||
@ -285,7 +278,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
# total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200
|
||||
tax_paid = get_tax_paid_in_period(employee)
|
||||
try:
|
||||
self.assertEqual(tax_paid, 121211)
|
||||
self.assertEqual(tax_paid, annual_tax)
|
||||
except AssertionError:
|
||||
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
|
||||
raise
|
||||
@ -327,6 +320,7 @@ def make_employee_salary_slip(user, payroll_frequency, salary_structure=None):
|
||||
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
|
||||
if not salary_structure:
|
||||
salary_structure = payroll_frequency + " Salary Structure Test for Salary Slip"
|
||||
|
||||
employee = frappe.db.get_value("Employee", {"user_id": user})
|
||||
salary_structure_doc = make_salary_structure(salary_structure, payroll_frequency, employee)
|
||||
salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
|
||||
@ -456,17 +450,15 @@ def make_deduction_salary_component(setup=False, test_tax=False, company_list=No
|
||||
{
|
||||
"salary_component": 'Professional Tax',
|
||||
"abbr":'PT',
|
||||
"condition": 'base > 10000',
|
||||
"formula": 'base*.1',
|
||||
"type": "Deduction",
|
||||
"amount_based_on_formula": 1
|
||||
"amount": 200,
|
||||
"exempted_from_income_tax": 1
|
||||
|
||||
},
|
||||
{
|
||||
"salary_component": 'TDS',
|
||||
"abbr":'T',
|
||||
"formula": 'base*.1',
|
||||
"type": "Deduction",
|
||||
"amount_based_on_formula": 1,
|
||||
"depends_on_payment_days": 0,
|
||||
"variable_based_on_taxable_salary": 1,
|
||||
"round_to_the_nearest_integer": 1
|
||||
@ -477,9 +469,7 @@ def make_deduction_salary_component(setup=False, test_tax=False, company_list=No
|
||||
"salary_component": 'TDS',
|
||||
"abbr":'T',
|
||||
"condition": 'employment_type=="Intern"',
|
||||
"formula": 'base*.1',
|
||||
"type": "Deduction",
|
||||
"amount_based_on_formula": 1,
|
||||
"round_to_the_nearest_integer": 1
|
||||
})
|
||||
if setup or test_tax:
|
||||
@ -535,29 +525,47 @@ def create_benefit_claim(employee, payroll_period, amount, component):
|
||||
}).submit()
|
||||
return claim_date
|
||||
|
||||
def create_tax_slab(payroll_period):
|
||||
data = [
|
||||
def create_tax_slab(payroll_period, effective_date = None, allow_tax_exemption = False, dont_submit = False):
|
||||
if frappe.db.exists("Income Tax Slab", "Tax Slab: " + payroll_period.name):
|
||||
return
|
||||
|
||||
slabs = [
|
||||
{
|
||||
"from_amount": 250000,
|
||||
"to_amount": 500000,
|
||||
"percent_deduction": 5.2,
|
||||
"percent_deduction": 5,
|
||||
"condition": "annual_taxable_earning > 500000"
|
||||
},
|
||||
{
|
||||
"from_amount": 500001,
|
||||
"to_amount": 1000000,
|
||||
"percent_deduction": 20.8
|
||||
"percent_deduction": 20
|
||||
},
|
||||
{
|
||||
"from_amount": 1000001,
|
||||
"percent_deduction": 31.2
|
||||
"percent_deduction": 30
|
||||
}
|
||||
]
|
||||
payroll_period.taxable_salary_slabs = []
|
||||
for item in data:
|
||||
payroll_period.append("taxable_salary_slabs", item)
|
||||
payroll_period.standard_tax_exemption_amount = 52500
|
||||
payroll_period.save()
|
||||
|
||||
income_tax_slab = frappe.new_doc("Income Tax Slab")
|
||||
income_tax_slab.name = "Tax Slab: " + payroll_period.name
|
||||
income_tax_slab.effective_from = effective_date or add_days(payroll_period.start_date, -2)
|
||||
|
||||
if allow_tax_exemption:
|
||||
income_tax_slab.allow_tax_exemption = 1
|
||||
income_tax_slab.standard_tax_exemption_amount = 50000
|
||||
|
||||
for item in slabs:
|
||||
income_tax_slab.append("slabs", item)
|
||||
|
||||
income_tax_slab.append("other_taxes_and_charges", {
|
||||
"description": "cess",
|
||||
"percent": 4
|
||||
})
|
||||
|
||||
income_tax_slab.save()
|
||||
if not dont_submit:
|
||||
income_tax_slab.submit()
|
||||
|
||||
def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True):
|
||||
deducted_dates = []
|
||||
|
@ -82,6 +82,7 @@ frappe.ui.form.on('Salary Structure', {
|
||||
{fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
|
||||
{fieldname:'base_variable', fieldtype:'Section Break'},
|
||||
{fieldname:'from_date', fieldtype:'Date', label: __('From Date'), "reqd": 1},
|
||||
{fieldname:'income_tax_slab', fieldtype:'Link', label: __('Income Tax Slab'), options: 'Income Tax Slab'},
|
||||
{fieldname:'base_col_br', fieldtype:'Column Break'},
|
||||
{fieldname:'base', fieldtype:'Currency', label: __('Base')},
|
||||
{fieldname:'variable', fieldtype:'Currency', label: __('Variable')}
|
||||
|
@ -16,6 +16,7 @@ class SalaryStructure(Document):
|
||||
self.validate_amount()
|
||||
self.strip_condition_and_formula_fields()
|
||||
self.validate_max_benefits_with_flexi()
|
||||
self.validate_component_based_on_tax_slab()
|
||||
|
||||
def set_missing_values(self):
|
||||
overwritten_fields = ["depends_on_payment_days", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
|
||||
@ -34,6 +35,12 @@ class SalaryStructure(Document):
|
||||
for fieldname in overwritten_fields_if_missing:
|
||||
d.set(fieldname, component_default_value.get(fieldname))
|
||||
|
||||
def validate_component_based_on_tax_slab(self):
|
||||
for row in self.deductions:
|
||||
if row.variable_based_on_taxable_salary and (row.amount or row.formula):
|
||||
frappe.throw(_("Row #{0}: Cannot set amount or formula for Salary Component {1} with Variable Based On Taxable Salary")
|
||||
.format(row.idx, row.salary_component))
|
||||
|
||||
def validate_amount(self):
|
||||
if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet:
|
||||
frappe.throw(_("Net pay cannot be negative"))
|
||||
@ -82,21 +89,23 @@ class SalaryStructure(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def assign_salary_structure(self, company=None, grade=None, department=None, designation=None,employee=None,
|
||||
from_date=None, base=None,variable=None):
|
||||
from_date=None, base=None, variable=None, income_tax_slab=None):
|
||||
employees = self.get_employees(company= company, grade= grade,department= department,designation= designation,name=employee)
|
||||
|
||||
if employees:
|
||||
if len(employees) > 20:
|
||||
frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
|
||||
employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
|
||||
employees=employees, salary_structure=self,from_date=from_date,
|
||||
base=base, variable=variable, income_tax_slab=income_tax_slab)
|
||||
else:
|
||||
assign_salary_structure_for_employees(employees, self, from_date=from_date, base=base,variable=variable)
|
||||
assign_salary_structure_for_employees(employees, self, from_date=from_date,
|
||||
base=base, variable=variable, income_tax_slab=income_tax_slab)
|
||||
else:
|
||||
frappe.msgprint(_("No Employee Found"))
|
||||
|
||||
|
||||
|
||||
def assign_salary_structure_for_employees(employees, salary_structure, from_date=None, base=None,variable=None):
|
||||
def assign_salary_structure_for_employees(employees, salary_structure, from_date=None, base=None, variable=None, income_tax_slab=None):
|
||||
salary_structures_assignments = []
|
||||
existing_assignments_for = get_existing_assignments(employees, salary_structure, from_date)
|
||||
count=0
|
||||
@ -105,7 +114,8 @@ def assign_salary_structure_for_employees(employees, salary_structure, from_date
|
||||
continue
|
||||
count +=1
|
||||
|
||||
salary_structures_assignment = create_salary_structures_assignment(employee, salary_structure, from_date, base, variable)
|
||||
salary_structures_assignment = create_salary_structures_assignment(employee,
|
||||
salary_structure, from_date, base, variable, income_tax_slab)
|
||||
salary_structures_assignments.append(salary_structures_assignment)
|
||||
frappe.publish_progress(count*100/len(set(employees) - set(existing_assignments_for)), title = _("Assigning Structures..."))
|
||||
|
||||
@ -113,7 +123,7 @@ def assign_salary_structure_for_employees(employees, salary_structure, from_date
|
||||
frappe.msgprint(_("Structures have been assigned successfully"))
|
||||
|
||||
|
||||
def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable):
|
||||
def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable, income_tax_slab=None):
|
||||
assignment = frappe.new_doc("Salary Structure Assignment")
|
||||
assignment.employee = employee
|
||||
assignment.salary_structure = salary_structure.name
|
||||
@ -121,6 +131,7 @@ def create_salary_structures_assignment(employee, salary_structure, from_date, b
|
||||
assignment.from_date = from_date
|
||||
assignment.base = base
|
||||
assignment.variable = variable
|
||||
assignment.income_tax_slab = income_tax_slab
|
||||
assignment.save(ignore_permissions = True)
|
||||
assignment.submit()
|
||||
return assignment.name
|
||||
|
@ -9,8 +9,9 @@ from frappe.utils.make_random import get_random
|
||||
from frappe.utils import nowdate, add_days, add_years, getdate, add_months
|
||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.hr.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\
|
||||
make_deduction_salary_component, make_employee_salary_slip
|
||||
make_deduction_salary_component, make_employee_salary_slip, create_tax_slab
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
from erpnext.hr.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import create_payroll_period
|
||||
|
||||
|
||||
test_dependencies = ["Fiscal Year"]
|
||||
@ -70,10 +71,8 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
self.assertEqual(sal_slip.get("earnings")[1].amount, 3000)
|
||||
self.assertEqual(sal_slip.get("earnings")[2].amount, 25000)
|
||||
self.assertEqual(sal_slip.get("gross_pay"), 78000)
|
||||
self.assertEqual(sal_slip.get("deductions")[0].amount, 5000)
|
||||
self.assertEqual(sal_slip.get("deductions")[1].amount, 5000)
|
||||
self.assertEqual(sal_slip.get("total_deduction"), 10000)
|
||||
self.assertEqual(sal_slip.get("net_pay"), 68000)
|
||||
self.assertEqual(sal_slip.get("deductions")[0].amount, 200)
|
||||
self.assertEqual(sal_slip.get("net_pay"), 78000 - sal_slip.get("total_deduction"))
|
||||
|
||||
def test_whitespaces_in_formula_conditions_fields(self):
|
||||
salary_structure = make_salary_structure("Salary Structure Sample", "Monthly", dont_submit=True)
|
||||
@ -112,6 +111,7 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do
|
||||
test_tax=False, company=None):
|
||||
if test_tax:
|
||||
frappe.db.sql("""delete from `tabSalary Structure` where name=%s""",(salary_structure))
|
||||
|
||||
if not frappe.db.exists('Salary Structure', salary_structure):
|
||||
details = {
|
||||
"doctype": "Salary Structure",
|
||||
@ -124,7 +124,8 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do
|
||||
}
|
||||
if other_details and isinstance(other_details, dict):
|
||||
details.update(other_details)
|
||||
salary_structure_doc = frappe.get_doc(details).insert()
|
||||
salary_structure_doc = frappe.get_doc(details)
|
||||
salary_structure_doc.insert()
|
||||
if not dont_submit:
|
||||
salary_structure_doc.submit()
|
||||
else:
|
||||
@ -139,13 +140,18 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do
|
||||
def create_salary_structure_assignment(employee, salary_structure, from_date=None, company=None):
|
||||
if frappe.db.exists("Salary Structure Assignment", {"employee": employee}):
|
||||
frappe.db.sql("""delete from `tabSalary Structure Assignment` where employee=%s""",(employee))
|
||||
|
||||
payroll_period = create_payroll_period()
|
||||
create_tax_slab(payroll_period, allow_tax_exemption=True)
|
||||
|
||||
salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
|
||||
salary_structure_assignment.employee = employee
|
||||
salary_structure_assignment.base = 50000
|
||||
salary_structure_assignment.variable = 5000
|
||||
salary_structure_assignment.from_date = from_date or add_months(nowdate(), -1)
|
||||
salary_structure_assignment.from_date = from_date or add_days(nowdate(), -1)
|
||||
salary_structure_assignment.salary_structure = salary_structure
|
||||
salary_structure_assignment.company = company or erpnext.get_default_company()
|
||||
salary_structure_assignment.save(ignore_permissions=True)
|
||||
salary_structure_assignment.income_tax_slab = "Tax Slab: _Test Payroll Period"
|
||||
salary_structure_assignment.submit()
|
||||
return salary_structure_assignment
|
||||
|
@ -20,6 +20,16 @@ frappe.ui.form.on('Salary Structure Assignment', {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("income_tax_slab", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
docstatus: 1,
|
||||
disabled: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
employee: function(frm) {
|
||||
if(frm.doc.employee){
|
||||
|
@ -10,11 +10,12 @@
|
||||
"employee",
|
||||
"employee_name",
|
||||
"department",
|
||||
"designation",
|
||||
"company",
|
||||
"column_break_6",
|
||||
"designation",
|
||||
"salary_structure",
|
||||
"from_date",
|
||||
"company",
|
||||
"income_tax_slab",
|
||||
"section_break_7",
|
||||
"base",
|
||||
"column_break_9",
|
||||
@ -113,11 +114,17 @@
|
||||
"options": "Salary Structure Assignment",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "income_tax_slab",
|
||||
"fieldtype": "Link",
|
||||
"label": "Income Tax Slab",
|
||||
"options": "Income Tax Slab"
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-31 16:35:34.415099",
|
||||
"modified": "2020-04-25 18:24:23.617088",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Structure Assignment",
|
||||
|
@ -9,6 +9,8 @@ from frappe.model.document import Document
|
||||
from frappe.desk.form import assign_to
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
|
||||
class DuplicateDeclarationError(frappe.ValidationError): pass
|
||||
|
||||
class EmployeeBoardingController(Document):
|
||||
'''
|
||||
Create the project and the task for the boarding process
|
||||
@ -226,6 +228,17 @@ def get_employee_leave_policy(employee):
|
||||
else:
|
||||
frappe.throw(_("Please set leave policy for employee {0} in Employee / Grade record").format(employee))
|
||||
|
||||
def validate_duplicate_exemption_for_payroll_period(doctype, docname, payroll_period, employee):
|
||||
existing_record = frappe.db.exists(doctype, {
|
||||
"payroll_period": payroll_period,
|
||||
"employee": employee,
|
||||
'docstatus': ['<', 2],
|
||||
'name': ['!=', docname]
|
||||
})
|
||||
if existing_record:
|
||||
frappe.throw(_("{0} already exists for employee {1} and period {2}")
|
||||
.format(doctype, employee, payroll_period), DuplicateDeclarationError)
|
||||
|
||||
def validate_tax_declaration(declarations):
|
||||
subcategories = []
|
||||
for d in declarations:
|
||||
|
@ -669,4 +669,5 @@ erpnext.patches.v12_0.set_total_batch_quantity
|
||||
erpnext.patches.v12_0.rename_mws_settings_fields
|
||||
erpnext.patches.v12_0.set_updated_purpose_in_pick_list
|
||||
erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
|
||||
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
|
||||
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
|
||||
erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
|
||||
|
@ -5,8 +5,7 @@ def execute():
|
||||
frappe.reload_doc('hr', 'doctype', 'salary_detail')
|
||||
frappe.reload_doc('hr', 'doctype', 'salary_component')
|
||||
|
||||
frappe.db.sql("update `tabSalary Component` set is_payable=1, is_tax_applicable=1 where type='Earning'")
|
||||
frappe.db.sql("update `tabSalary Component` set is_payable=0 where type='Deduction'")
|
||||
frappe.db.sql("update `tabSalary Component` set is_tax_applicable=1 where type='Earning'")
|
||||
|
||||
frappe.db.sql("""update `tabSalary Component` set variable_based_on_taxable_salary=1
|
||||
where type='Deduction' and name in ('TDS', 'Tax Deducted at Source')""")
|
||||
|
0
erpnext/patches/v13_0/__init__.py
Normal file
0
erpnext/patches/v13_0/__init__.py
Normal file
@ -0,0 +1,99 @@
|
||||
# Copyright (c) 2019, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
|
||||
def execute():
|
||||
if not frappe.db.table_exists("Payroll Period"):
|
||||
return
|
||||
|
||||
for doctype in ("income_tax_slab", "salary_structure_assignment", "employee_other_income"):
|
||||
frappe.reload_doc("hr", "doctype", doctype)
|
||||
|
||||
|
||||
for company in frappe.get_all("Company"):
|
||||
payroll_periods = frappe.db.sql("""
|
||||
SELECT
|
||||
name, start_date, end_date, standard_tax_exemption_amount
|
||||
FROM
|
||||
`tabPayroll Period`
|
||||
WHERE company=%s
|
||||
ORDER BY start_date DESC
|
||||
""", company.name, as_dict = 1)
|
||||
|
||||
for i, period in enumerate(payroll_periods):
|
||||
income_tax_slab = frappe.new_doc("Income Tax Slab")
|
||||
income_tax_slab.name = "Tax Slab:" + period.name
|
||||
|
||||
if i == 0:
|
||||
income_tax_slab.disabled = 0
|
||||
else:
|
||||
income_tax_slab.disabled = 1
|
||||
|
||||
income_tax_slab.effective_from = period.start_date
|
||||
income_tax_slab.company = company.name
|
||||
income_tax_slab.allow_tax_exemption = 1
|
||||
income_tax_slab.standard_tax_exemption_amount = period.standard_tax_exemption_amount
|
||||
|
||||
income_tax_slab.flags.ignore_mandatory = True
|
||||
income_tax_slab.submit()
|
||||
|
||||
frappe.db.sql(
|
||||
""" UPDATE `tabTaxable Salary Slab`
|
||||
SET parent = %s , parentfield = 'slabs' , parenttype = "Income Tax Slab"
|
||||
WHERE parent = %s
|
||||
""", (income_tax_slab.name, period.name), as_dict = 1)
|
||||
|
||||
if i == 0:
|
||||
frappe.db.sql("""
|
||||
UPDATE
|
||||
`tabSalary Structure Assignment`
|
||||
set
|
||||
income_tax_slab = %s
|
||||
where
|
||||
company = %s
|
||||
and from_date >= %s
|
||||
and docstatus < 2
|
||||
""", (income_tax_slab.name, company.name, period.start_date))
|
||||
|
||||
# move other incomes to separate document
|
||||
migrated = []
|
||||
proofs = frappe.get_all("Employee Tax Exemption Proof Submission",
|
||||
filters = {'docstatus': 1},
|
||||
fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
|
||||
)
|
||||
for proof in proofs:
|
||||
if proof.income_from_other_sources:
|
||||
employee_other_income = frappe.new_doc("Employee Other Income")
|
||||
employee_other_income.employee = proof.employee
|
||||
employee_other_income.payroll_period = proof.payroll_period
|
||||
employee_other_income.company = proof.company
|
||||
employee_other_income.amount = proof.income_from_other_sources
|
||||
|
||||
try:
|
||||
employee_other_income.submit()
|
||||
migrated.append([proof.employee, proof.payroll_period])
|
||||
except:
|
||||
pass
|
||||
|
||||
declerations = frappe.get_all("Employee Tax Exemption Declaration",
|
||||
filters = {'docstatus': 1},
|
||||
fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
|
||||
)
|
||||
|
||||
for declaration in declerations:
|
||||
if declaration.income_from_other_sources \
|
||||
and [declaration.employee, declaration.payroll_period] not in migrated:
|
||||
employee_other_income = frappe.new_doc("Employee Other Income")
|
||||
employee_other_income.employee = declaration.employee
|
||||
employee_other_income.payroll_period = declaration.payroll_period
|
||||
employee_other_income.company = declaration.company
|
||||
employee_other_income.amount = declaration.income_from_other_sources
|
||||
|
||||
try:
|
||||
employee_other_income.submit()
|
||||
except:
|
||||
pass
|
@ -531,12 +531,18 @@ def make_fixtures(company=None):
|
||||
|
||||
def set_salary_components(docs):
|
||||
docs.extend([
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Provident Fund', 'description': 'Provident fund', 'type': 'Deduction'},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance', 'description': 'House Rent Allowance', 'type': 'Earning'},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Basic', 'description': 'Basic', 'type': 'Earning'},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Arrear', 'description': 'Arrear', 'type': 'Earning'},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment', 'description': 'Leave Encashment', 'type': 'Earning'}
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Professional Tax',
|
||||
'description': 'Professional Tax', 'type': 'Deduction', 'exempted_from_income_tax': 1},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Provident Fund',
|
||||
'description': 'Provident fund', 'type': 'Deduction', 'is_tax_applicable': 1},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance',
|
||||
'description': 'House Rent Allowance', 'type': 'Earning', 'is_tax_applicable': 1},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Basic',
|
||||
'description': 'Basic', 'type': 'Earning', 'is_tax_applicable': 1},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Arrear',
|
||||
'description': 'Arrear', 'type': 'Earning', 'is_tax_applicable': 1},
|
||||
{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment',
|
||||
'description': 'Leave Encashment', 'type': 'Earning', 'is_tax_applicable': 1}
|
||||
])
|
||||
|
||||
def set_tax_withholding_category(company):
|
||||
|
Loading…
x
Reference in New Issue
Block a user