Fixed conflict
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.json b/erpnext/hr/doctype/additional_salary/additional_salary.json
index e669e10..b29b30b 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.json
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.json
@@ -60,7 +60,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 1,
+ "in_list_view": 0,
"in_standard_filter": 0,
"label": "Company",
"length": 0,
@@ -94,7 +94,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
+ "in_standard_filter": 1,
"label": "Employee",
"length": 0,
"no_copy": 0,
@@ -107,7 +107,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
@@ -127,7 +127,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
"label": "Employee Name",
"length": 0,
@@ -161,7 +161,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
+ "in_standard_filter": 1,
"label": "Salary Component",
"length": 0,
"no_copy": 0,
@@ -174,7 +174,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
@@ -251,7 +251,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "from_date",
+ "fieldname": "payroll_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -260,7 +260,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
- "label": "From Date",
+ "label": "Payroll Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -271,39 +271,7 @@
"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": "to_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": "To 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,
+ "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
@@ -322,7 +290,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
"label": "Amount",
"length": 0,
@@ -381,6 +349,39 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "salary_slip",
+ "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": "Salary Slip",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Salary Slip",
+ "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,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -417,7 +418,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-07-26 12:05:16.337082",
+ "modified": "2018-07-28 17:50:25.725444",
"modified_by": "Administrator",
"module": "HR",
"name": "Additional Salary",
@@ -471,5 +472,6 @@
"sort_order": "DESC",
"title_field": "employee",
"track_changes": 1,
- "track_seen": 0
+ "track_seen": 0,
+ "track_views": 0
}
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py
index e758227..b54d726 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.py
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.py
@@ -17,11 +17,9 @@
def validate_dates(self):
date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
- if getdate(self.from_date) > getdate(self.to_date):
- frappe.throw(_("To date can not be less than from date"))
- elif date_of_joining and getdate(self.from_date) < getdate(date_of_joining):
- frappe.throw(_("From date can not be less than employee's joining date"))
- elif relieving_date and getdate(self.to_date) > getdate(relieving_date):
+ if date_of_joining and getdate(self.payroll_date) < getdate(date_of_joining):
+ frappe.throw(_("Payroll date can not be less than employee's joining date"))
+ elif relieving_date and getdate(self.payroll_date) > getdate(relieving_date):
frappe.throw(_("To date can not greater than employee's relieving date"))
def get_amount(self, sal_start_date, sal_end_date):
@@ -39,46 +37,27 @@
@frappe.whitelist()
def get_additional_salary_component(employee, start_date, end_date):
additional_components = frappe.db.sql("""
- select name from `tabAdditional Salary`
- where employee=%(employee)s
- and docstatus = 1
- and (
- (%(from_date)s between from_date and to_date)
- or (%(to_date)s between from_date and to_date)
- or (from_date between %(from_date)s and %(to_date)s)
- )""", {
+ select salary_component, sum(amount) as amount from `tabAdditional Salary`
+ where employee=%(employee)s
+ and docstatus = 1
+ and payroll_date between %(from_date)s and %(to_date)s
+ group by salary_component
+ """, {
'employee': employee,
'from_date': start_date,
'to_date': end_date
- })
+ }, as_dict=1)
- if additional_components:
- additional_components_array = []
- for additional_component in additional_components:
- additional_component_obj = frappe.get_doc("Additional Salary", additional_component[0])
- amount = additional_component_obj.get_amount(start_date, end_date)
- salary_component = frappe.get_doc("Salary Component", additional_component_obj.salary_component)
- added = False
- for added_component in additional_components_array:
- if added_component["struct_row"]["salary_component"] == salary_component.name:
- added_component["amount"] += amount
- added = True
- if added:
- continue
- struct_row = {}
- additional_components_dict = {}
- struct_row['depends_on_lwp'] = salary_component.depends_on_lwp
- struct_row['salary_component'] = salary_component.name
- struct_row['abbr'] = salary_component.salary_component_abbr
- struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total
- struct_row['is_tax_applicable'] = salary_component.is_tax_applicable
- struct_row['variable_based_on_taxable_salary'] = salary_component.variable_based_on_taxable_salary
- struct_row['is_additional_component'] = salary_component.is_additional_component
- additional_components_dict['amount'] = amount
- additional_components_dict['struct_row'] = struct_row
- additional_components_dict['type'] = salary_component.type
- additional_components_array.append(additional_components_dict)
+ additional_components_list = []
+ for d in additional_components:
+ component = frappe.get_doc("Salary Component", d.salary_component)
+ struct_row = {'salary_component': d.salary_component}
+ for field in ["depends_on_lwp", "abbr", "is_tax_applicable", "variable_based_on_taxable_salary", "is_additional_component"]:
+ struct_row[field] = component.get(field)
- if len(additional_components_array) > 0:
- return additional_components_array
- return False
+ additional_components_list.append({
+ 'amount': d.amount,
+ 'type': component.type,
+ 'struct_row': struct_row
+ })
+ return additional_components_list
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index a61210c..9944bc5 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -30,8 +30,7 @@
additional_salary.company = frappe.get_value("Employee", self.employee, "company")
additional_salary.employee = self.employee
additional_salary.salary_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
- additional_salary.from_date = self.encashment_date
- additional_salary.to_date = self.encashment_date
+ additional_salary.payroll_date = self.encashment_date
additional_salary.amount = self.encashment_amount
additional_salary.submit()
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
index 2d866ba..7eaa063 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
@@ -12,7 +12,6 @@
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
class PayrollEntry(Document):
-
def on_submit(self):
self.create_salary_slips()
@@ -97,41 +96,25 @@
Creates salary slip for selected employees if already not created
"""
self.check_permission('write')
- self.created = 1;
- emp_list = self.get_emp_list()
- ss_list = []
+ self.created = 1
+ emp_list = [d.employee for d in self.get_emp_list()]
if emp_list:
- for emp in emp_list:
- if not frappe.db.sql("""select
- name from `tabSalary Slip`
- where
- docstatus!= 2 and
- employee = %s and
- start_date >= %s and
- end_date <= %s and
- company = %s
- """, (emp['employee'], self.start_date, self.end_date, self.company)):
- ss = frappe.get_doc({
- "doctype": "Salary Slip",
- "salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
- "payroll_frequency": self.payroll_frequency,
- "start_date": self.start_date,
- "end_date": self.end_date,
- "employee": emp['employee'],
- "employee_name": frappe.get_value("Employee", {"name":emp['employee']}, "employee_name"),
- "company": self.company,
- "posting_date": self.posting_date,
- "deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits,
- "deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof
- })
- ss.insert()
- ss_dict = {}
- ss_dict["Employee Name"] = ss.employee_name
- ss_dict["Total Pay"] = fmt_money(ss.rounded_total,currency = frappe.defaults.get_global_default("currency"))
- ss_dict["Salary Slip"] = format_as_links(ss.name)[0]
- ss_list.append(ss_dict)
- return create_log(ss_list)
-
+ args = frappe._dict({
+ "salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
+ "payroll_frequency": self.payroll_frequency,
+ "start_date": self.start_date,
+ "end_date": self.end_date,
+ "company": self.company,
+ "posting_date": self.posting_date,
+ "deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits,
+ "deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof,
+ "payroll_entry": self.payroll_entry
+ })
+ if len(emp_list) > 50:
+ frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args)
+ else:
+ create_salary_slips_for_employees(emp_list, args, publish_progress=False)
+
def get_sal_slip_list(self, ss_status, as_dict=False):
"""
Returns list of salary slips based on selected criteria
@@ -151,9 +134,6 @@
"""
self.check_permission('write')
- # self.create_salary_slips()
-
- jv_name = ""
ss_list = self.get_sal_slip_list(ss_status=0)
submitted_ss = []
not_submitted_ss = []
@@ -175,14 +155,15 @@
except frappe.ValidationError:
not_submitted_ss.append(ss_dict)
+
if submitted_ss:
- jv_name = self.make_accrual_jv_entry()
+ self.make_accrual_jv_entry()
frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
.format(ss_obj.start_date, ss_obj.end_date))
self.email_salary_slip(submitted_ss)
- return create_submit_log(submitted_ss, not_submitted_ss, jv_name)
+ return create_submit_log(submitted_ss, not_submitted_ss)
def email_salary_slip(self, submitted_ss):
if frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee"):
@@ -509,28 +490,16 @@
else:
frappe.throw(_("Fiscal Year {0} not found").format(year))
-
-@frappe.whitelist()
-def create_log(ss_list):
- if not ss_list:
- frappe.throw(
- _("There's no employee for the given criteria. Check that Salary Slips have not already been created."),
- title='Error'
- )
- return ss_list
-
-
def format_as_links(salary_slip):
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(salary_slip)]
-def create_submit_log(submitted_ss, not_submitted_ss, jv_name):
-
+def create_submit_log(submitted_ss, not_submitted_ss):
if not submitted_ss and not not_submitted_ss:
frappe.msgprint(_("No salary slip found to submit for the above selected criteria OR salary slip already submitted"))
if not_submitted_ss:
- frappe.msgprint(_("Could not submit any Salary Slip <br>\
+ frappe.msgprint(_("Could not submit some Salary Slips <br>\
Possible reasons: <br>\
1. Net pay is less than 0. <br>\
2. Company Email Address specified in employee master is not valid. <br>"))
@@ -584,3 +553,26 @@
response['submitted'] = 1 if bank_entries else 0
return response
+
+def create_salary_slips_for_employees(employees, args, publish_progress=True):
+ salary_slips_exists_for = get_existing_salary_slips(employees, args)
+ count=0
+ for emp in employees:
+ if emp not in salary_slips_exists_for:
+ ss = frappe.new_doc("Salary Slip")
+ ss.employee = emp
+ ss.update(args)
+ ss.insert()
+ count+=1
+ if publish_progress:
+ frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)),
+ title = _("Creating Salary Slips..."))
+
+def get_existing_salary_slips(employees, args):
+ return frappe.db.sql_list("""
+ select distinct employee from `tabSalary Slip`
+ where docstatus!= 2 and company = %s
+ and start_date >= %s and end_date <= %s
+ and employee in (%s)
+ """ % ('%s', '%s', '%s', ', '.join(['%s']*len(employees))),
+ [args.company, args.start_date, args.end_date] + employees)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js
index 755bb40..cbbc9e9 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.js
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.js
@@ -39,10 +39,13 @@
start_date: function(frm, dt, dn){
if(frm.doc.start_date){
frm.trigger("set_end_date");
- get_emp_and_leave_details(frm.doc, dt, dn);
}
},
+ end_date: function(frm, dt, dn) {
+ get_emp_and_leave_details(frm.doc, dt, dn);
+ },
+
set_end_date: function(frm){
frappe.call({
method: 'erpnext.hr.doctype.payroll_entry.payroll_entry.get_end_date',
@@ -82,8 +85,6 @@
payroll_frequency: function(frm, dt, dn) {
frm.trigger("toggle_fields");
frm.set_value('end_date', '');
- frm.set_value('start_date', '');
- get_emp_and_leave_details(frm.doc, dt, dn);
},
employee: function(frm, dt, dn) {
@@ -121,21 +122,14 @@
// Get leave details
//---------------------------------------------------------------------
var get_emp_and_leave_details = function(doc, dt, dn) {
- if(!doc.start_date){
- return frappe.call({
- method: 'get_emp_and_leave_details',
- doc: locals[dt][dn],
- callback: function(r, rt) {
- cur_frm.refresh();
- calculate_all(doc, dt, dn);
- }
- });
- }
-}
-
-cur_frm.cscript.employee = function(doc,dt,dn){
- doc.salary_structure = ''
- get_emp_and_leave_details(doc, dt, dn);
+ return frappe.call({
+ method: 'get_emp_and_leave_details',
+ doc: locals[dt][dn],
+ callback: function(r, rt) {
+ cur_frm.refresh();
+ calculate_all(doc, dt, dn);
+ }
+ });
}
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json
index 473d6e3..2e2856d 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.json
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.json
@@ -325,6 +325,39 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "payroll_entry",
+ "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": "Payroll Entry",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payroll Entry",
+ "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,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -1872,7 +1905,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-06-28 12:18:50.538159",
+ "modified": "2018-07-27 19:23:35.587516",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip",
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 5a91796..f6e3208 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -241,10 +241,14 @@
if self.payroll_frequency:
cond += """and ss.payroll_frequency = '%(payroll_frequency)s'""" % {"payroll_frequency": self.payroll_frequency}
- st_name = frappe.db.sql("""select sa.salary_structure from `tabSalary Structure Assignment` sa
- join `tabSalary Structure` ss where sa.salary_structure=ss.name
- and sa.docstatus = 1 and ss.docstatus = 1 and ss.is_active ='Yes' %s
- order by sa.from_date desc limit 1 """ %cond, {'employee': self.employee, 'start_date': self.start_date,
+ st_name = frappe.db.sql("""
+ select sa.salary_structure
+ from `tabSalary Structure Assignment` sa join `tabSalary Structure` ss
+ where sa.salary_structure=ss.name
+ and sa.docstatus = 1 and ss.docstatus = 1 and ss.is_active ='Yes' %s
+ order by sa.from_date desc
+ limit 1
+ """ %cond, {'employee': self.employee, 'start_date': self.start_date,
'end_date': self.end_date, 'joining_date': joining_date})
if st_name:
@@ -480,17 +484,26 @@
else:
self.set_status()
self.update_status(self.name)
+ self.update_salary_slip_in_additional_salary()
if (frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry:
self.email_salary_slip()
def on_cancel(self):
self.set_status()
self.update_status()
+ self.update_salary_slip_in_additional_salary()
def on_trash(self):
from frappe.model.naming import revert_series_if_last
revert_series_if_last(self.series, self.name)
+ def update_salary_slip_in_additional_salary(self):
+ salary_slip = self.name if self.docstatus==1 else None
+ frappe.db.sql("""
+ update `tabAdditional Salary` set salary_slip=%s
+ where employee=%s and payroll_date between %s and %s and docstatus=1
+ """, (salary_slip, self.employee, self.start_date, self.end_date))
+
def email_salary_slip(self):
receiver = frappe.db.get_value("Employee", self.employee, "prefered_email")
diff --git a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
index 95308dc..66cb910 100644
--- a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
+++ b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
@@ -28,7 +28,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
+ "in_standard_filter": 1,
"label": "Employee",
"length": 0,
"no_copy": 0,
@@ -41,7 +41,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
@@ -129,7 +129,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
+ "in_standard_filter": 1,
"label": "Salary Structure",
"length": 0,
"no_copy": 0,
@@ -142,7 +142,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
@@ -412,7 +412,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-06-22 14:54:05.494234",
+ "modified": "2018-07-27 16:23:17.490097",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Structure Assignment",
@@ -485,5 +485,6 @@
"sort_order": "DESC",
"title_field": "employee_name",
"track_changes": 1,
- "track_seen": 0
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file