Merge pull request #16306 from rohitwaghchaure/removed_duplicate_fields
[Fix] Duplicate fieldnames operation and allow_alternative_item in BOM Item
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 66d9bad..d518cd8 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -13,8 +13,8 @@
from erpnext.utilities.transaction_base import delete_events
from frappe.utils.nestedset import NestedSet
-class EmployeeUserDisabledError(frappe.ValidationError):
- pass
+class EmployeeUserDisabledError(frappe.ValidationError): pass
+class EmployeeLeftValidationError(frappe.ValidationError): pass
class Employee(NestedSet):
nsm_parent_field = 'reports_to'
@@ -147,8 +147,16 @@
validate_email_add(self.personal_email, True)
def validate_status(self):
- if self.status == 'Left' and not self.relieving_date:
- throw(_("Please enter relieving date."))
+ if self.status == 'Left':
+ reports_to = frappe.db.get_all('Employee',
+ filters={'reports_to': self.name}
+ )
+ if reports_to:
+ link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name) for employee in reports_to]
+ throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ")
+ + ', '.join(link_to_employees), EmployeeLeftValidationError)
+ if not self.relieving_date:
+ throw(_("Please enter relieving date."))
def validate_for_enabled_user_id(self, enabled):
if not self.status == 'Active':
diff --git a/erpnext/hr/doctype/employee/test_employee.py b/erpnext/hr/doctype/employee/test_employee.py
index 1afb8f4..5a63beb 100644
--- a/erpnext/hr/doctype/employee/test_employee.py
+++ b/erpnext/hr/doctype/employee/test_employee.py
@@ -7,6 +7,7 @@
import erpnext
import unittest
import frappe.utils
+from erpnext.hr.doctype.employee.employee import EmployeeLeftValidationError
test_records = frappe.get_test_records('Employee')
@@ -32,6 +33,18 @@
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue("Subject: Birthday Reminder" in email_queue[0].message)
+ def test_employee_status_left(self):
+ employee1 = make_employee("test_employee_1@company.com")
+ employee2 = make_employee("test_employee_2@company.com")
+ employee1_doc = frappe.get_doc("Employee", employee1)
+ employee2_doc = frappe.get_doc("Employee", employee2)
+ employee2_doc.reload()
+ employee2_doc.reports_to = employee1_doc.name
+ employee2_doc.save()
+ employee1_doc.reload()
+ employee1_doc.status = 'Left'
+ self.assertRaises(EmployeeLeftValidationError, employee1_doc.save)
+
def make_employee(user):
if not frappe.db.get_value("User", user):
frappe.get_doc({
diff --git a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
new file mode 100644
index 0000000..5ab2847
--- /dev/null
+++ b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import getdate
+from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data
+from erpnext.hr.doctype.employee.test_employee import make_employee
+
+class TestUploadAttendance(unittest.TestCase):
+ def test_date_range(self):
+ employee = make_employee("test_employee@company.com")
+ employee_doc = frappe.get_doc("Employee", employee)
+ date_of_joining = "2018-01-02"
+ relieving_date = "2018-01-03"
+ from_date = "2018-01-01"
+ to_date = "2018-01-04"
+ employee_doc.date_of_joining = date_of_joining
+ employee_doc.relieving_date = relieving_date
+ employee_doc.save()
+ args = {
+ "from_date": from_date,
+ "to_date": to_date
+ }
+ data = get_data(args)
+ filtered_data = []
+ for row in data:
+ if row[1] == employee:
+ filtered_data.append(row)
+ print(filtered_data)
+ for row in filtered_data:
+ self.assertTrue(getdate(row[3]) >= getdate(date_of_joining) and getdate(row[3]) <= getdate(relieving_date))
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index 3d080a7..db74b10 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -41,16 +41,28 @@
return w
def add_data(w, args):
+ data = get_data(args)
+ writedata(w, data)
+ return w
+
+def get_data(args):
dates = get_dates(args)
employees = get_active_employees()
existing_attendance_records = get_existing_attendance_records(args)
+ data = []
for date in dates:
for employee in employees:
+ if getdate(date) < getdate(employee.date_of_joining):
+ continue
+ if employee.relieving_date:
+ if getdate(date) > getdate(employee.relieving_date):
+ continue
existing_attendance = {}
if existing_attendance_records \
- and tuple([getdate(date), employee.name]) in existing_attendance_records:
+ and tuple([getdate(date), employee.name]) in existing_attendance_records \
+ and getdate(employee.date_of_joining) >= getdate(date) \
+ and getdate(employee.relieving_date) <= getdate(date):
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
-
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -58,8 +70,12 @@
existing_attendance and existing_attendance.leave_type or "", employee.company,
existing_attendance and existing_attendance.naming_series or get_naming_series(),
]
- w.writerow(row)
- return w
+ data.append(row)
+ return data
+
+def writedata(w, data):
+ for row in data:
+ w.writerow(row)
def get_dates(args):
"""get list of dates in between from date and to date"""
@@ -68,8 +84,13 @@
return dates
def get_active_employees():
- employees = frappe.db.sql("""select name, employee_name, company
- from tabEmployee where docstatus < 2 and status = 'Active'""", as_dict=1)
+ employees = frappe.db.get_all('Employee',
+ fields=['name', 'employee_name', 'date_of_joining', 'company', 'relieving_date'],
+ filters={
+ 'docstatus': ['<', 2],
+ 'status': 'Active'
+ }
+ )
return employees
def get_existing_attendance_records(args):