Merge pull request #17373 from netchampfaris/item-attribute-order-dynamic
fix: Order Item attribute values dynamically
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 7ab7f14..d224961 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -285,6 +285,7 @@
is_paid: function() {
hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_paid)) {
+ this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
this.frm.set_value("is_paid", 0)
frappe.msgprint(__("Please specify Company to proceed"));
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 90a0ef4..f21fbd9 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -369,7 +369,7 @@
set_pos_data: function() {
if(this.frm.doc.is_pos) {
- this.frm.set_value("allocate_advances_automatically", this.frm.doc.is_pos ? 0 : 1);
+ this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
this.frm.set_value("is_pos", 0);
frappe.msgprint(__("Please specify Company to proceed"));
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index f358b4a..48663ca 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -359,7 +359,8 @@
"from_date": from_date,
"to_date": to_date,
"cost_center": filters.cost_center,
- "project": filters.project
+ "project": filters.project,
+ "finance_book": filters.get("finance_book")
},
as_dict=True)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 90dc086..155a996 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -89,7 +89,8 @@
self.validate_paid_amount()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
- if cint(self.allocate_advances_automatically) and not cint(self.is_pos):
+ pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
+ if cint(self.allocate_advances_automatically) and not cint(self.get(pos_check_field)):
self.set_advances()
if self.is_return:
diff --git a/erpnext/hr/doctype/employee_tax_exemption_category/employee_tax_exemption_category.json b/erpnext/hr/doctype/employee_tax_exemption_category/employee_tax_exemption_category.json
index 7b2804b..66fac5b 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_category/employee_tax_exemption_category.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_category/employee_tax_exemption_category.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "max_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -29,7 +31,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
- "label": "Max Amount",
+ "label": "Max Exemption Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -39,7 +41,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -52,6 +54,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "default": "1",
+ "fetch_if_empty": 0,
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
@@ -88,7 +92,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-06-19 16:33:48.419267",
+ "modified": "2019-04-25 13:20:31.367158",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Category",
@@ -159,6 +163,7 @@
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.js b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.js
index 9560df5..a827eca 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.js
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.js
@@ -10,6 +10,7 @@
}
}
});
+
frm.set_query('payroll_period', function() {
const fields = {'employee': 'Employee', 'company': 'Company'};
@@ -27,6 +28,7 @@
}
}
});
+
frm.set_query('exemption_sub_category', 'declarations', function() {
return {
filters: {
@@ -34,5 +36,16 @@
}
}
});
+ },
+
+ refresh: function(frm) {
+ if(frm.doc.docstatus==1) {
+ frm.add_custom_button(__('Submit Proof'), function() {
+ frappe.model.open_mapped_doc({
+ method: "erpnext.hr.doctype.employee_tax_exemption_declaration.employee_tax_exemption_declaration.make_proof_submission",
+ frm: frm
+ });
+ }).addClass("btn-primary");
+ }
}
});
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
index 899b869..8891b97 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
@@ -55,9 +55,43 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fetch_from": "employee.company",
+ "fetch_from": "employee.employee_name",
"fetch_if_empty": 0,
- "fieldname": "company",
+ "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
+ },
+ {
+ "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,
@@ -66,15 +100,15 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Company",
+ "label": "Department",
"length": 0,
"no_copy": 0,
- "options": "Company",
+ "options": "Department",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -156,42 +190,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_from": "employee.company",
"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_from": "employee.department",
- "fetch_if_empty": 0,
- "fieldname": "department",
+ "fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -200,15 +201,15 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Department",
+ "label": "Company",
"length": 0,
"no_copy": 0,
- "options": "Department",
+ "options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -315,6 +316,136 @@
"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_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
+ },
+ {
+ "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
+ },
+ {
+ "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
+ },
+ {
+ "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
}
],
"has_web_view": 0,
@@ -327,7 +458,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-04-23 15:50:48.693555",
+ "modified": "2019-04-25 16:38:05.847925",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Declaration",
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
index 186b2e1..cbdfcf8 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
@@ -6,28 +6,61 @@
import frappe
from frappe.model.document import Document
from frappe import _
-from erpnext.hr.utils import validate_tax_declaration, calculate_annual_eligible_hra_exemption
+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
class EmployeeTaxExemptionDeclaration(Document):
def validate(self):
validate_tax_declaration(self.declarations)
- self.total_exemption_amount = 0
+ self.validate_duplicate()
+ self.set_total_declared_amount()
+ self.set_total_exemption_amount()
self.calculate_hra_exemption()
- for item in self.declarations:
- self.total_exemption_amount += item.amount
- def before_submit(self):
- if frappe.db.exists({"doctype": "Employee Tax Exemption Declaration",
- "employee": self.employee,
- "payroll_period": self.payroll_period,
- "docstatus": 1}):
- frappe.throw(_("Tax Declaration of {0} for period {1} already submitted.")\
- .format(self.employee, self.payroll_period), frappe.DocstatusTransitionError)
+ 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]
+ }
+ )
+ 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:
+ self.total_declared_amount += flt(d.amount)
+
+ def set_total_exemption_amount(self):
+ self.total_exemption_amount = get_total_exemption_amount(self.declarations)
def calculate_hra_exemption(self):
- hra_exemption = calculate_annual_eligible_hra_exemption(self)
- if hra_exemption:
- self.total_exemption_amount += hra_exemption["annual_exemption"]
- self.salary_structure_hra = hra_exemption["hra_amount"]
- self.annual_hra_exemption = hra_exemption["annual_exemption"]
- self.monthly_hra_exemption = hra_exemption["monthly_exemption"]
+ self.salary_structure_hra, self.annual_hra_exemption, self.monthly_hra_exemption = 0, 0, 0
+ if self.get("monthly_house_rent"):
+ hra_exemption = calculate_annual_eligible_hra_exemption(self)
+ if hra_exemption:
+ self.total_exemption_amount += hra_exemption["annual_exemption"]
+ self.salary_structure_hra = hra_exemption["hra_amount"]
+ self.annual_hra_exemption = hra_exemption["annual_exemption"]
+ self.monthly_hra_exemption = hra_exemption["monthly_exemption"]
+
+@frappe.whitelist()
+def make_proof_submission(source_name, target_doc=None):
+ doclist = get_mapped_doc("Employee Tax Exemption Declaration", source_name, {
+ "Employee Tax Exemption Declaration": {
+ "doctype": "Employee Tax Exemption Proof Submission",
+ "field_no_map": ["monthly_house_rent", "monthly_hra_exemption"]
+ },
+ "Employee Tax Exemption Declaration Category": {
+ "doctype": "Employee Tax Exemption Proof Submission Detail",
+ "add_if_empty": True
+ }
+ }, target_doc)
+
+ return doclist
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
index beaddd9..9c87bbd 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
@@ -6,6 +6,7 @@
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
class TestEmployeeTaxExemptionDeclaration(unittest.TestCase):
def setUp(self):
@@ -15,71 +16,71 @@
create_exemption_category()
frappe.db.sql("""delete from `tabEmployee Tax Exemption Declaration`""")
- def test_exemption_amount_greater_than_category_max(self):
- declaration = frappe.get_doc({
- "doctype": "Employee Tax Exemption Declaration",
- "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
- "payroll_period": "_Test Payroll Period",
- "declarations": [dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 150000)]
- })
- self.assertRaises(frappe.ValidationError, declaration.save)
- declaration = frappe.get_doc({
- "doctype": "Employee Tax Exemption Declaration",
- "payroll_period": "_Test Payroll Period",
- "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
- "declarations": [dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 90000)]
- })
- self.assertTrue(declaration.save)
-
def test_duplicate_category_in_declaration(self):
declaration = frappe.get_doc({
"doctype": "Employee Tax Exemption Declaration",
"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
"company": erpnext.get_default_company(),
"payroll_period": "_Test Payroll Period",
- "declarations": [dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 100000),
- dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 50000),
- ]
+ "declarations": [
+ dict(exemption_sub_category = "_Test Sub Category",
+ exemption_category = "_Test Category",
+ amount = 100000),
+ dict(exemption_sub_category = "_Test Sub Category",
+ exemption_category = "_Test Category",
+ amount = 50000)
+ ]
})
self.assertRaises(frappe.ValidationError, declaration.save)
- def test_duplicate_submission_for_payroll_period(self):
+ def test_duplicate_entry_for_payroll_period(self):
declaration = frappe.get_doc({
"doctype": "Employee Tax Exemption Declaration",
"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
"company": erpnext.get_default_company(),
"payroll_period": "_Test Payroll Period",
- "declarations": [dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 100000),
- dict(exemption_sub_category = "_Test1 Sub Category",
- exemption_category = "_Test Category",
- amount = 50000),
- ]
+ "declarations": [
+ dict(exemption_sub_category = "_Test Sub Category",
+ exemption_category = "_Test Category",
+ amount = 100000),
+ dict(exemption_sub_category = "_Test1 Sub Category",
+ exemption_category = "_Test Category",
+ amount = 50000),
+ ]
}).insert()
- declaration.submit()
- self.assertEquals(declaration.docstatus, 1)
+
duplicate_declaration = frappe.get_doc({
"doctype": "Employee Tax Exemption Declaration",
"employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
"company": erpnext.get_default_company(),
"payroll_period": "_Test Payroll Period",
- "declarations": [dict(exemption_sub_category = "_Test Sub Category",
- exemption_category = "_Test Category",
- amount = 100000)
- ]
- }).insert()
- self.assertRaises(frappe.DocstatusTransitionError, duplicate_declaration.submit)
+ "declarations": [
+ dict(exemption_sub_category = "_Test Sub Category",
+ exemption_category = "_Test Category",
+ amount = 100000)
+ ]
+ })
+ self.assertRaises(DuplicateDeclarationError, duplicate_declaration.insert)
duplicate_declaration.employee = frappe.get_value("Employee", {"user_id":"employee1@taxexepmtion.com"}, "name")
- self.assertTrue(duplicate_declaration.submit)
+ self.assertTrue(duplicate_declaration.insert)
+
+ def test_exemption_amount(self):
+ declaration = frappe.get_doc({
+ "doctype": "Employee Tax Exemption Declaration",
+ "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"),
+ "company": erpnext.get_default_company(),
+ "payroll_period": "_Test Payroll Period",
+ "declarations": [
+ dict(exemption_sub_category = "_Test Sub Category",
+ exemption_category = "_Test Category",
+ amount = 80000),
+ dict(exemption_sub_category = "_Test1 Sub Category",
+ exemption_category = "_Test Category",
+ amount = 60000),
+ ]
+ }).insert()
+
+ self.assertEqual(declaration.total_exemption_amount, 100000)
def create_payroll_period():
if not frappe.db.exists("Payroll Period", "_Test Payroll Period"):
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json b/erpnext/hr/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
index ebde4c9..56556c1 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json
@@ -1,140 +1,179 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-04-13 16:56:23.333041",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-04-13 16:56:23.333041",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "exemption_sub_category",
- "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": "Exemption Sub Category",
- "length": 0,
- "no_copy": 0,
- "options": "Employee Tax Exemption Sub 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 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": "exemption_sub_category",
+ "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": "Exemption Sub Category",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee Tax Exemption Sub 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": 1,
+ "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_from": "exemption_sub_category.exemption_category",
- "fieldname": "exemption_category",
- "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": "Exemption Category",
- "length": 0,
- "no_copy": 0,
- "options": "Employee Tax Exemption 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_from": "exemption_sub_category.exemption_category",
+ "fetch_if_empty": 0,
+ "fieldname": "exemption_category",
+ "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": "Exemption Category",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee Tax Exemption Category",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Currency",
- "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": "Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_from": "exemption_sub_category.max_amount",
+ "fetch_if_empty": 0,
+ "fieldname": "max_amount",
+ "fieldtype": "Currency",
+ "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": "Maximum 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": 1,
+ "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": "amount",
+ "fieldtype": "Data",
+ "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": "Declared Amount",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-05-29 15:58:05.779031",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Employee Tax Exemption Declaration Category",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "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
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-04-25 15:45:11.279158",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Tax Exemption Declaration Category",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "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
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
index 99bec14..66118c0 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js
@@ -10,6 +10,7 @@
}
}
});
+
frm.set_query('payroll_period', function() {
if(frm.doc.employee && frm.doc.company){
return {
@@ -21,6 +22,7 @@
frappe.msgprint(__("Please select Employee"));
}
});
+
frm.set_query('exemption_sub_category', 'tax_exemption_proofs', function() {
return {
filters: {
@@ -29,11 +31,28 @@
}
});
},
- employee: function(frm){
- if(frm.doc.employee){
- frm.add_fetch('employee', 'company', 'company');
- }else{
- frm.set_value('company', '');
+
+ refresh: function(frm) {
+ if(frm.doc.docstatus === 0) {
+ let filters = {
+ docstatus: 1,
+ company: frm.doc.company
+ };
+ if(frm.doc.employee) filters["employee"] = frm.doc.employee;
+ if(frm.doc.payroll_period) filters["payroll_period"] = frm.doc.payroll_period;
+
+ frm.add_custom_button(__('Get Details From Declaration'), function() {
+ erpnext.utils.map_current_doc({
+ method: "erpnext.hr.doctype.employee_tax_exemption_declaration.employee_tax_exemption_declaration.make_proof_submission",
+ source_doctype: "Employee Tax Exemption Declaration",
+ target: frm,
+ date_field: "creation",
+ setters: {
+ employee: frm.doc.employee || undefined
+ },
+ get_query_filters: filters
+ });
+ });
}
}
});
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
index ebc0435..76c09d6 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
@@ -1,8 +1,9 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
"autoname": "HR-TAX-PRF-.YYYY.-.#####",
"beta": 0,
"creation": "2018-04-13 17:24:11.456132",
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
@@ -53,8 +55,10 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
+ "fetch_from": "employee.employee_name",
+ "fetch_if_empty": 0,
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -62,10 +66,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Company",
+ "label": "Employee Name",
"length": 0,
"no_copy": 0,
- "options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -86,71 +89,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_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
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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
- },
- {
- "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,
@@ -184,8 +124,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "submission_date",
- "fieldtype": "Date",
+ "fetch_if_empty": 0,
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -193,7 +134,6 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Submission Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -216,6 +156,273 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "default": "Today",
+ "fetch_if_empty": 0,
+ "fieldname": "submission_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": "Submission 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
+ },
+ {
+ "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
+ },
+ {
+ "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": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "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_5",
+ "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
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "tax_exemption_proofs",
+ "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": "Tax Exemption Proofs",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee Tax Exemption Proof Submission Detail",
+ "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_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
+ },
+ {
+ "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_actual_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 Actual 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": "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
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "exemption_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -248,70 +455,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "section_break_5",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "tax_exemption_proofs",
- "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": "Tax Exemption Proofs",
- "length": 0,
- "no_copy": 0,
- "options": "Employee Tax Exemption Proof Submission Detail",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "attachment_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -344,6 +488,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "attachments",
"fieldtype": "Attach",
"hidden": 0,
@@ -376,6 +521,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -412,7 +558,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-08-21 16:15:38.096846",
+ "modified": "2019-04-25 17:06:36.569549",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Proof Submission",
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
index 54e0b20..97ceb63 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
@@ -6,20 +6,30 @@
import frappe
from frappe.model.document import Document
from frappe import _
-from erpnext.hr.utils import validate_tax_declaration, calculate_hra_exemption_for_period
+from frappe.utils import flt
+from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, calculate_hra_exemption_for_period
class EmployeeTaxExemptionProofSubmission(Document):
def validate(self):
validate_tax_declaration(self.tax_exemption_proofs)
- self.exemption_amount = 0
+ self.set_total_actual_amount()
+ self.set_total_exemption_amount()
self.calculate_hra_exemption()
- for proof in self.tax_exemption_proofs:
- self.exemption_amount += proof.amount
+
+ def set_total_actual_amount(self):
+ self.total_actual_amount = flt(self.get("house_rent_payment_amount"))
+ for d in self.tax_exemption_proofs:
+ self.total_actual_amount += flt(d.amount)
+
+ def set_total_exemption_amount(self):
+ self.exemption_amount = get_total_exemption_amount(self.tax_exemption_proofs)
def calculate_hra_exemption(self):
- hra_exemption = calculate_hra_exemption_for_period(self)
- if hra_exemption:
- 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.monthly_hra_exemption, self.monthly_house_rent, self.total_eligible_hra_exemption = 0, 0, 0
+ if self.get("house_rent_payment_amount"):
+ hra_exemption = calculate_hra_exemption_for_period(self)
+ if hra_exemption:
+ 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"]
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json b/erpnext/hr/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
index c1c5896..b9254af 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,10 +15,12 @@
"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": "exemption_sub_category",
"fieldtype": "Link",
"hidden": 0,
@@ -41,16 +44,18 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 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_from": "exemption_sub_category.exemption_category",
+ "fetch_from": "exemption_sub_category.exemption_category",
+ "fetch_if_empty": 0,
"fieldname": "exemption_category",
"fieldtype": "Read Only",
"hidden": 0,
@@ -74,15 +79,51 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 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_from": "exemption_sub_category.max_amount",
+ "fetch_if_empty": 0,
+ "fieldname": "max_amount",
+ "fieldtype": "Currency",
+ "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": "Maximum 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": 1,
+ "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": "type_of_proof",
"fieldtype": "Data",
"hidden": 0,
@@ -106,15 +147,17 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 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": "amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -124,7 +167,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
- "label": "Amount",
+ "label": "Actual Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -134,10 +177,10 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -151,7 +194,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-05-16 22:42:59.750733",
+ "modified": "2019-04-25 15:45:03.154904",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Proof Submission Detail",
@@ -165,5 +208,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
- "track_seen": 0
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.json b/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.json
index dc99785..b0e492e 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -15,10 +16,12 @@
"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": "exemption_category",
"fieldtype": "Link",
"hidden": 0,
@@ -26,8 +29,8 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
"label": "Tax Exemption Category",
"length": 0,
"no_copy": 0,
@@ -42,14 +45,18 @@
"reqd": 1,
"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_from": "exemption_category.max_amount",
+ "fetch_if_empty": 1,
"fieldname": "max_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -59,7 +66,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
- "label": "Max Amount",
+ "label": "Max Exemption Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -69,17 +76,21 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "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,
+ "default": "1",
+ "fetch_if_empty": 0,
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
@@ -102,6 +113,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -115,7 +127,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-09 13:25:01.595240",
+ "modified": "2019-04-25 13:24:05.164877",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Sub Category",
@@ -124,7 +136,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -144,7 +155,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -164,7 +174,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -189,6 +198,7 @@
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py b/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py
index cd58136..a8dd7e4 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_sub_category/employee_tax_exemption_sub_category.py
@@ -4,7 +4,13 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
+from frappe.utils import flt
from frappe.model.document import Document
class EmployeeTaxExemptionSubCategory(Document):
- pass
+ def validate(self):
+ category_max_amount = frappe.db.get_value("Employee Tax Exemption Category", self.exemption_category, "max_amount")
+ if flt(self.max_amount) > flt(category_max_amount):
+ frappe.throw(_("Max Exemption Amount cannot be greater than maximum exemption amount {0} of Tax Exemption Category {1}")
+ .format(category_max_amount, self.exemption_category))
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index 079bec5..746bf8c 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -13,7 +13,8 @@
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
from erpnext.hr.doctype.payroll_entry.payroll_entry import get_month_details
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, create_exemption_category
+from erpnext.hr.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration \
+ import create_payroll_period, create_exemption_category
class TestSalarySlip(unittest.TestCase):
def setUp(self):
@@ -36,8 +37,10 @@
no_of_days = self.get_no_of_days()
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
make_employee("test_employee@salary.com")
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
self.assertEqual(ss.total_working_days, no_of_days[0])
@@ -53,8 +56,10 @@
no_of_days = self.get_no_of_days()
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
make_employee("test_employee@salary.com")
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
self.assertEqual(ss.total_working_days, no_of_days[0] - no_of_days[1])
@@ -100,16 +105,21 @@
self.assertEqual(ss.payment_days, (no_of_days[0] - getdate(date_of_joining).day + 1))
# set relieving date in the same month
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", relieving_date)
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
+ frappe.db.set_value("Employee",frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", relieving_date)
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
ss.save()
self.assertEqual(ss.total_working_days, no_of_days[0])
self.assertEqual(ss.payment_days, getdate(relieving_date).day)
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
- frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
+ frappe.db.set_value("Employee", frappe.get_value("Employee",
+ {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
def test_employee_salary_slip_read_permission(self):
make_employee("test_employee@salary.com")
@@ -168,17 +178,22 @@
def test_tax_for_payroll_period(self):
data = {}
- # test the impact of tax exemption declaration, tax exemption proof submission and deduct check boxes in annual tax calculation
+ # test the impact of tax exemption declaration, tax exemption proof submission
+ # and deduct check boxes in annual tax calculation
# 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)
employee = make_employee("test_tax@salary.slip")
- delete_docs = ["Salary Slip", "Additional Salary",
- "Employee Tax Exemption Declaration",
- "Employee Tax Exemption Proof Submission",
- "Employee Benefit Claim", "Salary Structure Assignment"]
+ delete_docs = [
+ "Salary Slip",
+ "Additional Salary",
+ "Employee Tax Exemption Declaration",
+ "Employee Tax Exemption Proof Submission",
+ "Employee Benefit Claim",
+ "Salary Structure Assignment"
+ ]
for doc in delete_docs:
frappe.db.sql("delete from `tab%s` where employee='%s'" % (doc, employee))
@@ -298,12 +313,11 @@
if not salary_slip:
salary_slip = make_salary_slip(salary_structure_doc.name, employee = employee)
- salary_slip.employee_name = frappe.get_value("Employee", {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
+ salary_slip.employee_name = frappe.get_value("Employee",
+ {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
salary_slip.payroll_frequency = payroll_frequency
salary_slip.posting_date = nowdate()
salary_slip.insert()
- # salary_slip.submit()
- # salary_slip = salary_slip.name
return salary_slip
@@ -338,99 +352,99 @@
salary_account = frappe.db.get_value("Account", "Salary - " + frappe.get_cached_value('Company', company, 'abbr'))
if not salary_account:
frappe.get_doc({
- "doctype": "Account",
- "account_name": "Salary",
- "parent_account": "Indirect Expenses - " + frappe.get_cached_value('Company', company, 'abbr'),
- "company": company
+ "doctype": "Account",
+ "account_name": "Salary",
+ "parent_account": "Indirect Expenses - " + frappe.get_cached_value('Company', company, 'abbr'),
+ "company": company
}).insert()
return salary_account
def make_earning_salary_component(setup=False, test_tax=False):
data = [
+ {
+ "salary_component": 'Basic Salary',
+ "abbr":'BS',
+ "condition": 'base > 10000',
+ "formula": 'base*.5',
+ "type": "Earning",
+ "amount_based_on_formula": 1
+ },
+ {
+ "salary_component": 'HRA',
+ "abbr":'H',
+ "amount": 3000,
+ "type": "Earning"
+ },
+ {
+ "salary_component": 'Special Allowance',
+ "abbr":'SA',
+ "condition": 'H < 10000',
+ "formula": 'BS*.5',
+ "type": "Earning",
+ "amount_based_on_formula": 1
+ },
+ {
+ "salary_component": "Leave Encashment",
+ "abbr": 'LE',
+ "is_additional_component": 1,
+ "type": "Earning"
+ }
+ ]
+ if test_tax:
+ data.extend([
{
- "salary_component": 'Basic Salary',
- "abbr":'BS',
- "condition": 'base > 10000',
- "formula": 'base*.5',
+ "salary_component": "Leave Travel Allowance",
+ "abbr": 'B',
+ "is_flexible_benefit": 1,
"type": "Earning",
- "amount_based_on_formula": 1
+ "pay_against_benefit_claim": 1,
+ "max_benefit_amount": 100000
},
{
- "salary_component": 'HRA',
- "abbr":'H',
- "amount": 3000,
- "type": "Earning"
- },
- {
- "salary_component": 'Special Allowance',
- "abbr":'SA',
- "condition": 'H < 10000',
- "formula": 'BS*.5',
+ "salary_component": "Medical Allowance",
+ "abbr": 'B',
+ "is_flexible_benefit": 1,
+ "pay_against_benefit_claim": 0,
"type": "Earning",
- "amount_based_on_formula": 1
+ "max_benefit_amount": 15000
},
{
- "salary_component": "Leave Encashment",
- "abbr": 'LE',
+ "salary_component": "Perfomance Bonus",
+ "abbr": 'B',
"is_additional_component": 1,
"type": "Earning"
}
- ]
- if test_tax:
- data.extend([
- {
- "salary_component": "Leave Travel Allowance",
- "abbr": 'B',
- "is_flexible_benefit": 1,
- "type": "Earning",
- "pay_against_benefit_claim": 1,
- "max_benefit_amount": 100000
- },
- {
- "salary_component": "Medical Allowance",
- "abbr": 'B',
- "is_flexible_benefit": 1,
- "pay_against_benefit_claim": 0,
- "type": "Earning",
- "max_benefit_amount": 15000
- },
- {
- "salary_component": "Perfomance Bonus",
- "abbr": 'B',
- "is_additional_component": 1,
- "type": "Earning"
- }
- ])
+ ])
if setup or test_tax:
make_salary_component(data, test_tax)
data.append({
- "salary_component": 'Basic Salary',
- "abbr":'BS',
- "condition": 'base < 10000',
- "formula": 'base*.2',
- "type": "Earning",
- "amount_based_on_formula": 1
- })
+ "salary_component": 'Basic Salary',
+ "abbr":'BS',
+ "condition": 'base < 10000',
+ "formula": 'base*.2',
+ "type": "Earning",
+ "amount_based_on_formula": 1
+ })
return data
def make_deduction_salary_component(setup=False, test_tax=False):
data = [
- {
- "salary_component": 'Professional Tax',
- "abbr":'PT',
- "condition": 'base > 10000',
- "formula": 'base*.1',
- "type": "Deduction",
- "amount_based_on_formula": 1
- },
- {
- "salary_component": 'TDS',
- "abbr":'T',
- "formula": 'base*.1',
- "type": "Deduction",
- "amount_based_on_formula": 1
- }
- ]
+ {
+ "salary_component": 'Professional Tax',
+ "abbr":'PT',
+ "condition": 'base > 10000',
+ "formula": 'base*.1',
+ "type": "Deduction",
+ "amount_based_on_formula": 1
+ },
+ {
+ "salary_component": 'TDS',
+ "abbr":'T',
+ "formula": 'base*.1',
+ "type": "Deduction",
+ "amount_based_on_formula": 1
+ }
+ ]
if not test_tax:
data.append({
"salary_component": 'TDS',
@@ -453,48 +467,63 @@
def create_exemption_declaration(employee, payroll_period):
create_exemption_category()
- declaration = frappe.get_doc({"doctype": "Employee Tax Exemption Declaration",
- "employee": employee,
- "payroll_period": payroll_period,
- "company": erpnext.get_default_company()})
- declaration.append("declarations", {"exemption_sub_category": "_Test Sub Category",
- "exemption_category": "_Test Category",
- "amount": 100000})
+ declaration = frappe.get_doc({
+ "doctype": "Employee Tax Exemption Declaration",
+ "employee": employee,
+ "payroll_period": payroll_period,
+ "company": erpnext.get_default_company()
+ })
+ declaration.append("declarations", {
+ "exemption_sub_category": "_Test Sub Category",
+ "exemption_category": "_Test Category",
+ "amount": 100000
+ })
declaration.submit()
def create_proof_submission(employee, payroll_period, amount):
submission_date = add_months(payroll_period.start_date, random.randint(0, 11))
- proof_submission = frappe.get_doc({"doctype": "Employee Tax Exemption Proof Submission",
- "employee": employee,
- "payroll_period": payroll_period.name,
- "submission_date": submission_date})
- proof_submission.append("tax_exemption_proofs", {"exemption_sub_category": "_Test Sub Category",
- "exemption_category": "_Test Category", "type_of_proof": "Test", "amount": amount})
+ proof_submission = frappe.get_doc({
+ "doctype": "Employee Tax Exemption Proof Submission",
+ "employee": employee,
+ "payroll_period": payroll_period.name,
+ "submission_date": submission_date
+ })
+ proof_submission.append("tax_exemption_proofs", {
+ "exemption_sub_category": "_Test Sub Category",
+ "exemption_category": "_Test Category",
+ "type_of_proof": "Test", "amount": amount
+ })
proof_submission.submit()
return submission_date
def create_benefit_claim(employee, payroll_period, amount, component):
claim_date = add_months(payroll_period.start_date, random.randint(0, 11))
- frappe.get_doc({"doctype": "Employee Benefit Claim", "employee": employee,
- "claimed_amount": amount, "claim_date": claim_date, "earning_component":
- component}).submit()
+ frappe.get_doc({
+ "doctype": "Employee Benefit Claim",
+ "employee": employee,
+ "claimed_amount": amount,
+ "claim_date": claim_date,
+ "earning_component": component
+ }).submit()
return claim_date
def create_tax_slab(payroll_period):
- data = [{
- "from_amount": 250000,
- "to_amount": 500000,
- "percent_deduction": 5
- },
- {
- "from_amount": 500000,
- "to_amount": 1000000,
- "percent_deduction": 20
- },
- {
- "from_amount": 1000000,
- "percent_deduction": 30
- }]
+ data = [
+ {
+ "from_amount": 250000,
+ "to_amount": 500000,
+ "percent_deduction": 5
+ },
+ {
+ "from_amount": 500000,
+ "to_amount": 1000000,
+ "percent_deduction": 20
+ },
+ {
+ "from_amount": 1000000,
+ "percent_deduction": 30
+ }
+ ]
payroll_period.taxable_salary_slabs = []
for item in data:
payroll_period.append("taxable_salary_slabs", item)
@@ -526,9 +555,13 @@
def create_additional_salary(employee, payroll_period, amount):
salary_date = add_months(payroll_period.start_date, random.randint(0, 11))
- frappe.get_doc({"doctype": "Additional Salary", "employee": employee,
- "company": erpnext.get_default_company(),
- "salary_component": "Perfomance Bonus",
- "payroll_date": salary_date,
- "amount": amount, "type": "Earning"}).submit()
+ frappe.get_doc({
+ "doctype": "Additional Salary",
+ "employee": employee,
+ "company": erpnext.get_default_company(),
+ "salary_component": "Perfomance Bonus",
+ "payroll_date": salary_date,
+ "amount": amount,
+ "type": "Earning"
+ }).submit()
return salary_date
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index 313cfc4..a600e75 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -221,16 +221,30 @@
def validate_tax_declaration(declarations):
subcategories = []
- for declaration in declarations:
- if declaration.exemption_sub_category in subcategories:
- frappe.throw(_("More than one selection for {0} not \
- allowed").format(declaration.exemption_sub_category), frappe.ValidationError)
- subcategories.append(declaration.exemption_sub_category)
- max_amount = frappe.db.get_value("Employee Tax Exemption Sub Category", \
- declaration.exemption_sub_category, "max_amount")
- if declaration.amount > max_amount:
- frappe.throw(_("Max exemption amount for {0} is {1}").format(\
- declaration.exemption_sub_category, max_amount), frappe.ValidationError)
+ for d in declarations:
+ if d.exemption_sub_category in subcategories:
+ frappe.throw(_("More than one selection for {0} not allowed").format(d.exemption_sub_category))
+ subcategories.append(d.exemption_sub_category)
+
+def get_total_exemption_amount(declarations):
+ exemptions = frappe._dict()
+ for d in declarations:
+ exemptions.setdefault(d.exemption_category, frappe._dict())
+ category_max_amount = exemptions.get(d.exemption_category).max_amount
+ if not category_max_amount:
+ category_max_amount = frappe.db.get_value("Employee Tax Exemption Category", d.exemption_category, "max_amount")
+ exemptions.get(d.exemption_category).max_amount = category_max_amount
+ sub_category_exemption_amount = d.max_amount \
+ if (d.max_amount and flt(d.amount) > flt(d.max_amount)) else d.amount
+
+ exemptions.get(d.exemption_category).setdefault("total_exemption_amount", 0.0)
+ exemptions.get(d.exemption_category).total_exemption_amount += flt(sub_category_exemption_amount)
+
+ if category_max_amount and exemptions.get(d.exemption_category).total_exemption_amount > category_max_amount:
+ exemptions.get(d.exemption_category).total_exemption_amount = category_max_amount
+
+ total_exemption_amount = sum([flt(d.total_exemption_amount) for d in exemptions.values()])
+ return total_exemption_amount
def get_leave_period(from_date, to_date, company):
leave_period = frappe.db.sql("""
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 6b583af..f3a4f7c 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -284,18 +284,18 @@
'Employee Tax Exemption Declaration':[
dict(fieldname='hra_section', label='HRA Exemption',
fieldtype='Section Break', insert_after='declarations'),
- dict(fieldname='salary_structure_hra', label='HRA as per Salary Structure',
- fieldtype='Currency', insert_after='hra_section', read_only=1),
dict(fieldname='monthly_house_rent', label='Monthly House Rent',
- fieldtype='Currency', insert_after='salary_structure_hra'),
+ fieldtype='Currency', insert_after='hra_section'),
dict(fieldname='rented_in_metro_city', label='Rented in Metro City',
- fieldtype='Check', insert_after='monthly_house_rent'),
+ fieldtype='Check', insert_after='monthly_house_rent', depends_on='monthly_house_rent'),
+ dict(fieldname='salary_structure_hra', label='HRA as per Salary Structure',
+ fieldtype='Currency', insert_after='rented_in_metro_city', read_only=1, depends_on='monthly_house_rent'),
dict(fieldname='hra_column_break', fieldtype='Column Break',
- insert_after='rented_in_metro_city'),
+ insert_after='salary_structure_hra', depends_on='monthly_house_rent'),
dict(fieldname='annual_hra_exemption', label='Annual HRA Exemption',
- fieldtype='Currency', insert_after='hra_column_break', read_only=1),
+ fieldtype='Currency', insert_after='hra_column_break', read_only=1, depends_on='monthly_house_rent'),
dict(fieldname='monthly_hra_exemption', label='Monthly HRA Exemption',
- fieldtype='Currency', insert_after='annual_hra_exemption', read_only=1)
+ fieldtype='Currency', insert_after='annual_hra_exemption', read_only=1, depends_on='monthly_house_rent')
],
'Employee Tax Exemption Proof Submission': [
dict(fieldname='hra_section', label='HRA Exemption',
@@ -303,19 +303,19 @@
dict(fieldname='house_rent_payment_amount', label='House Rent Payment Amount',
fieldtype='Currency', insert_after='hra_section'),
dict(fieldname='rented_in_metro_city', label='Rented in Metro City',
- fieldtype='Check', insert_after='house_rent_payment_amount'),
+ fieldtype='Check', insert_after='house_rent_payment_amount', depends_on='house_rent_payment_amount'),
dict(fieldname='rented_from_date', label='Rented From Date',
- fieldtype='Date', insert_after='rented_in_metro_city'),
+ fieldtype='Date', insert_after='rented_in_metro_city', depends_on='house_rent_payment_amount'),
dict(fieldname='rented_to_date', label='Rented To Date',
- fieldtype='Date', insert_after='rented_from_date'),
+ fieldtype='Date', insert_after='rented_from_date', depends_on='house_rent_payment_amount'),
dict(fieldname='hra_column_break', fieldtype='Column Break',
- insert_after='rented_to_date'),
+ insert_after='rented_to_date', depends_on='house_rent_payment_amount'),
dict(fieldname='monthly_house_rent', label='Monthly House Rent',
- fieldtype='Currency', insert_after='hra_column_break', read_only=1),
+ fieldtype='Currency', insert_after='hra_column_break', read_only=1, depends_on='house_rent_payment_amount'),
dict(fieldname='monthly_hra_exemption', label='Monthly Eligible Amount',
- fieldtype='Currency', insert_after='monthly_house_rent', read_only=1),
+ fieldtype='Currency', insert_after='monthly_house_rent', read_only=1, depends_on='house_rent_payment_amount'),
dict(fieldname='total_eligible_hra_exemption', label='Total Eligible HRA Exemption',
- fieldtype='Currency', insert_after='monthly_hra_exemption', read_only=1)
+ fieldtype='Currency', insert_after='monthly_hra_exemption', read_only=1, depends_on='house_rent_payment_amount')
],
'Supplier': [
{
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index e379ed8..f413a8e 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -1,7 +1,7 @@
from __future__ import unicode_literals
import frappe, re
from frappe import _
-from frappe.utils import cstr, flt, date_diff, getdate
+from frappe.utils import cstr, flt, date_diff, nowdate
from erpnext.regional.india import states, state_numbers
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -144,24 +144,40 @@
def calculate_annual_eligible_hra_exemption(doc):
basic_component = frappe.get_cached_value('Company', doc.company, "basic_component")
hra_component = frappe.get_cached_value('Company', doc.company, "hra_component")
+ if not (basic_component and hra_component):
+ frappe.throw(_("Please mention Basic and HRA component in Company"))
+
annual_exemption, monthly_exemption, hra_amount = 0, 0, 0
if hra_component and basic_component:
- assignment = get_salary_assignment(doc.employee, getdate())
- if assignment and frappe.db.exists("Salary Detail", {
- "parent": assignment.salary_structure,
- "salary_component": hra_component, "parentfield": "earnings"}):
- basic_amount, hra_amount = get_component_amt_from_salary_slip(doc.employee,
- assignment.salary_structure, basic_component, hra_component)
- if hra_amount:
- if doc.monthly_house_rent:
- annual_exemption = calculate_hra_exemption(assignment.salary_structure,
- basic_amount, hra_amount, doc.monthly_house_rent,
- doc.rented_in_metro_city)
- if annual_exemption > 0:
- monthly_exemption = annual_exemption / 12
- else:
- annual_exemption = 0
- return {"hra_amount": hra_amount, "annual_exemption": annual_exemption, "monthly_exemption": monthly_exemption}
+ assignment = get_salary_assignment(doc.employee, nowdate())
+
+ if assignment:
+ hra_component_exists = frappe.db.exists("Salary Detail", {
+ "parent": assignment.salary_structure,
+ "salary_component": hra_component,
+ "parentfield": "earnings",
+ "parenttype": "Salary Structure"
+ })
+ if hra_component_exists:
+ basic_amount, hra_amount = get_component_amt_from_salary_slip(doc.employee,
+ assignment.salary_structure, basic_component, hra_component)
+ if hra_amount:
+ if doc.monthly_house_rent:
+ annual_exemption = calculate_hra_exemption(assignment.salary_structure,
+ basic_amount, hra_amount, doc.monthly_house_rent,
+ doc.rented_in_metro_city)
+ if annual_exemption > 0:
+ monthly_exemption = annual_exemption / 12
+ else:
+ annual_exemption = 0
+ elif doc.docstatus == 1:
+ frappe.throw(_("Salary Structure must be submitted before submission of Tax Ememption Declaration"))
+
+ return frappe._dict({
+ "hra_amount": hra_amount,
+ "annual_exemption": annual_exemption,
+ "monthly_exemption": monthly_exemption
+ })
def get_component_amt_from_salary_slip(employee, salary_structure, basic_component, hra_component):
salary_slip = make_salary_slip(salary_structure, employee=employee)
@@ -181,8 +197,10 @@
frequency = frappe.get_value("Salary Structure", salary_structure, "payroll_frequency")
# case 1: The actual amount allotted by the employer as the HRA.
exemptions.append(get_annual_component_pay(frequency, monthly_hra))
+
actual_annual_rent = monthly_house_rent * 12
annual_basic = get_annual_component_pay(frequency, basic)
+
# case 2: Actual rent paid less 10% of the basic salary.
exemptions.append(flt(actual_annual_rent) - flt(annual_basic * 0.1))
# case 3: 50% of the basic salary, if the employee is staying in a metro city (40% for a non-metro city).
@@ -205,15 +223,25 @@
def validate_house_rent_dates(doc):
if not doc.rented_to_date or not doc.rented_from_date:
frappe.throw(_("House rented dates required for exemption calculation"))
+
if date_diff(doc.rented_to_date, doc.rented_from_date) < 14:
frappe.throw(_("House rented dates should be atleast 15 days apart"))
- proofs = frappe.db.sql("""select name from `tabEmployee Tax Exemption Proof Submission`
- where docstatus=1 and employee='{0}' and payroll_period='{1}' and
- (rented_from_date between '{2}' and '{3}' or rented_to_date between
- '{2}' and '{3}')""".format(doc.employee, doc.payroll_period,
- doc.rented_from_date, doc.rented_to_date))
+
+ proofs = frappe.db.sql("""
+ select name
+ from `tabEmployee Tax Exemption Proof Submission`
+ where
+ docstatus=1 and employee=%(employee)s and payroll_period=%(payroll_period)s
+ and (rented_from_date between %(from_date)s and %(to_date)s or rented_to_date between %(from_date)s and %(to_date)s)
+ """, {
+ "employee": doc.employee,
+ "payroll_period": doc.payroll_period,
+ "from_date": doc.rented_from_date,
+ "to_date": doc.rented_to_date
+ })
+
if proofs:
- frappe.throw(_("House rent paid days overlap with {0}").format(proofs[0][0]))
+ frappe.throw(_("House rent paid days overlapping with {0}").format(proofs[0][0]))
def calculate_hra_exemption_for_period(doc):
monthly_rent, eligible_hra = 0, 0