feat: consider carry forwarded leaves on creation of encashment
This commit is contained in:
		
							parent
							
								
									314647572c
								
							
						
					
					
						commit
						5cbe6160ca
					
				| @ -63,14 +63,14 @@ frappe.ui.form.on("Leave Allocation", { | ||||
| 		frm.trigger("calculate_total_leaves_allocated"); | ||||
| 	}, | ||||
| 
 | ||||
| 	carry_forwarded_leaves: function(frm) { | ||||
| 	unused_leaves: function(frm) { | ||||
| 		frm.set_value("total_leaves_allocated", | ||||
| 			flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated)); | ||||
| 			flt(frm.doc.unused_leaves) + flt(frm.doc.new_leaves_allocated)); | ||||
| 	}, | ||||
| 
 | ||||
| 	new_leaves_allocated: function(frm) { | ||||
| 		frm.set_value("total_leaves_allocated", | ||||
| 			flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated)); | ||||
| 			flt(frm.doc.unused_leaves) + flt(frm.doc.new_leaves_allocated)); | ||||
| 	}, | ||||
| 
 | ||||
| 	leave_policy: function(frm) { | ||||
| @ -93,7 +93,7 @@ frappe.ui.form.on("Leave Allocation", { | ||||
| 				} | ||||
| 			}) | ||||
| 		} else if (cint(frm.doc.carry_forward) == 0) { | ||||
| 			frm.set_value("carry_forwarded_leaves", 0); | ||||
| 			frm.set_value("unused_leaves", 0); | ||||
| 			frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -17,13 +17,14 @@ | ||||
|   "section_break_6", | ||||
|   "new_leaves_allocated", | ||||
|   "carry_forward", | ||||
|   "carry_forwarded_leaves", | ||||
|   "unused_leaves", | ||||
|   "total_leaves_allocated", | ||||
|   "total_leaves_encashed", | ||||
|   "column_break_10", | ||||
|   "compensatory_request", | ||||
|   "leave_period", | ||||
|   "leave_policy", | ||||
|   "carry_forwarded_leaves_count", | ||||
|   "expired", | ||||
|   "amended_from", | ||||
|   "notes", | ||||
| @ -119,7 +120,7 @@ | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "carry_forward", | ||||
|    "fieldname": "carry_forwarded_leaves", | ||||
|    "fieldname": "unused_leaves", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Unused leaves", | ||||
|    "read_only": 1 | ||||
| @ -167,6 +168,15 @@ | ||||
|    "options": "Leave Policy", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "expired", | ||||
|    "fieldtype": "Check", | ||||
|    "hidden": 1, | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Expired", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "amended_from", | ||||
|    "fieldtype": "Link", | ||||
| @ -194,19 +204,17 @@ | ||||
|    "width": "300px" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "expired", | ||||
|    "fieldtype": "Check", | ||||
|    "hidden": 1, | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Expired", | ||||
|    "depends_on": "carry_forwarded_leaves_count", | ||||
|    "fieldname": "carry_forwarded_leaves_count", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Carry Forwarded Leaves", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-ok", | ||||
|  "idx": 1, | ||||
|  "is_submittable": 1, | ||||
|  "modified": "2019-07-22 17:50:39.591195", | ||||
|  "modified": "2019-08-08 15:08:42.440909", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "HR", | ||||
|  "name": "Leave Allocation", | ||||
|  | ||||
| @ -50,6 +50,8 @@ class LeaveAllocation(Document): | ||||
| 
 | ||||
| 	def on_cancel(self): | ||||
| 		self.create_leave_ledger_entry(submit=False) | ||||
| 		if self.carry_forward: | ||||
| 			self.set_carry_forwarded_leaves_in_previous_allocation(on_cancel=True) | ||||
| 
 | ||||
| 	def validate_period(self): | ||||
| 		if date_diff(self.to_date, self.from_date) <= 0: | ||||
| @ -89,24 +91,33 @@ class LeaveAllocation(Document): | ||||
| 					BackDatedAllocationError) | ||||
| 
 | ||||
| 	def set_total_leaves_allocated(self): | ||||
| 		self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, | ||||
| 		self.unused_leaves = get_carry_forwarded_leaves(self.employee, | ||||
| 			self.leave_type, self.from_date, self.carry_forward) | ||||
| 
 | ||||
| 		self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated) | ||||
| 		self.maintain_carry_forwarded_leaves() | ||||
| 		self.total_leaves_allocated = flt(self.unused_leaves) + flt(self.new_leaves_allocated) | ||||
| 
 | ||||
| 		if self.carry_forward: | ||||
| 			self.maintain_carry_forwarded_leaves() | ||||
| 			self.set_carry_forwarded_leaves_in_previous_allocation() | ||||
| 
 | ||||
| 		if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"): | ||||
| 			frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type))) | ||||
| 			frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}").format(self.leave_type)) | ||||
| 
 | ||||
| 	def maintain_carry_forwarded_leaves(self): | ||||
| 		''' reduce the carry forwarded leaves to be within the maximum allowed leaves ''' | ||||
| 		if not self.carry_forward: | ||||
| 			return | ||||
| 		''' Reduce the carry forwarded leaves to be within the maximum allowed leaves ''' | ||||
| 		 | ||||
| 		max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed") | ||||
| 		if self.new_leaves_allocated <= max_leaves_allowed <= self.total_leaves_allocated: | ||||
| 			self.carry_forwarded_leaves = max_leaves_allowed - flt(self.new_leaves_allocated) | ||||
| 			self.unused_leaves = max_leaves_allowed - flt(self.new_leaves_allocated) | ||||
| 			self.total_leaves_allocated = flt(max_leaves_allowed) | ||||
| 
 | ||||
| 	def set_carry_forwarded_leaves_in_previous_allocation(self, on_cancel=False): | ||||
| 		''' Set carry forwarded leaves in previous allocation ''' | ||||
| 		previous_allocation = get_previous_allocation(self.from_date, self.leave_type, self.employee) | ||||
| 		if on_cancel: | ||||
| 			self.unused_leaves = 0.0 | ||||
| 		frappe.db.set_value("Leave Allocation", previous_allocation.name, 'carry_forwarded_leaves_count', self.unused_leaves) | ||||
| 
 | ||||
| 	def validate_total_leaves_allocated(self): | ||||
| 		# Adding a day to include To Date in the difference | ||||
| 		date_difference = date_diff(self.to_date, self.from_date) + 1 | ||||
| @ -114,10 +125,10 @@ class LeaveAllocation(Document): | ||||
| 			frappe.throw(_("Total allocated leaves are more than days in the period"), OverAllocationError) | ||||
| 
 | ||||
| 	def create_leave_ledger_entry(self, submit=True): | ||||
| 		if self.carry_forwarded_leaves: | ||||
| 		if self.unused_leaves: | ||||
| 			expiry_days = frappe.db.get_value("Leave Type", self.leave_type, "expire_carried_forward_leaves") | ||||
| 			args = dict( | ||||
| 				leaves=self.carry_forwarded_leaves, | ||||
| 				leaves=self.unused_leaves, | ||||
| 				from_date=self.from_date, | ||||
| 				to_date=add_days(self.from_date, expiry_days - 1) if expiry_days else self.to_date, | ||||
| 				is_carry_forward=1 | ||||
| @ -142,7 +153,7 @@ def get_previous_allocation(from_date, leave_type, employee): | ||||
| 			'docstatus': 1 | ||||
| 		}, | ||||
| 		order_by='to_date DESC', | ||||
| 		fieldname=['name', 'from_date', 'to_date'], as_dict=1) | ||||
| 		fieldname=['name', 'from_date', 'to_date', 'employee', 'leave_type'], as_dict=1) | ||||
| 
 | ||||
| def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): | ||||
| 	leave_allocated = 0 | ||||
| @ -170,13 +181,13 @@ def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): | ||||
| @frappe.whitelist() | ||||
| def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None): | ||||
| 	''' Returns carry forwarded leaves for the given employee ''' | ||||
| 	carry_forwarded_leaves = 0.0 | ||||
| 	unused_leaves = 0.0 | ||||
| 	previous_allocation = get_previous_allocation(date, leave_type, employee) | ||||
| 	if carry_forward and previous_allocation: | ||||
| 		validate_carry_forward(leave_type) | ||||
| 		carry_forwarded_leaves = get_unused_leaves(employee, leave_type, previous_allocation.from_date, previous_allocation.to_date) | ||||
| 		unused_leaves = get_unused_leaves(employee, leave_type, previous_allocation.from_date, previous_allocation.to_date) | ||||
| 
 | ||||
| 	return carry_forwarded_leaves | ||||
| 	return unused_leaves | ||||
| 
 | ||||
| def get_unused_leaves(employee, leave_type, from_date, to_date): | ||||
| 	''' Returns unused leaves between the given period while skipping leave allocation expiry ''' | ||||
|  | ||||
| @ -64,7 +64,8 @@ class LeaveEncashment(Document): | ||||
| 
 | ||||
| 		allocation = self.get_leave_allocation() | ||||
| 
 | ||||
| 		self.leave_balance = allocation.total_leaves_allocated - get_unused_leaves(self.employee, self.leave_type, allocation.from_date, self.encashment_date) | ||||
| 		self.leave_balance = allocation.total_leaves_allocated - allocation.carry_forwarded_leaves_count\ | ||||
| 			- get_unused_leaves(self.employee, self.leave_type, allocation.from_date, self.encashment_date) | ||||
| 
 | ||||
| 		encashable_days = self.leave_balance - frappe.db.get_value('Leave Type', self.leave_type, 'encashment_threshold_days') | ||||
| 		self.encashable_days = encashable_days if encashable_days > 0 else 0 | ||||
| @ -76,9 +77,9 @@ class LeaveEncashment(Document): | ||||
| 		return True | ||||
| 
 | ||||
| 	def get_leave_allocation(self): | ||||
| 		leave_allocation = frappe.db.sql("""select name, to_date, total_leaves_allocated from `tabLeave Allocation` where '{0}' | ||||
| 		leave_allocation = frappe.db.sql("""select name, to_date, total_leaves_allocated, carry_forwarded_leaves_count from `tabLeave Allocation` where '{0}' | ||||
| 		between from_date and to_date and docstatus=1 and leave_type='{1}' | ||||
| 		and employee= '{2}'""".format(self.encashment_date or getdate(nowdate()), self.leave_type, self.employee), as_dict=1) | ||||
| 		and employee= '{2}'""".format(self.encashment_date or getdate(nowdate()), self.leave_type, self.employee), as_dict=1) #nosec | ||||
| 
 | ||||
| 		return leave_allocation[0] if leave_allocation else None | ||||
| 
 | ||||
|  | ||||
| @ -104,7 +104,7 @@ def process_expired_allocation(): | ||||
| 				`transaction_type`='Leave Allocation' | ||||
| 				AND `is_expired`=1""") | ||||
| 
 | ||||
| 		expire_allocation = frappe.get_all("Leave Ledger Entry",  | ||||
| 		expire_allocation = frappe.get_all("Leave Ledger Entry", | ||||
| 			fields=['leaves', 'to_date', 'employee', 'leave_type', 'is_carry_forward', 'transaction_name as name', 'transaction_type'], | ||||
| 			filters={ | ||||
| 				'to_date': ("<", today()), | ||||
| @ -119,9 +119,9 @@ def process_expired_allocation(): | ||||
| 	if expire_allocation: | ||||
| 		create_expiry_ledger_entry(expire_allocation) | ||||
| 
 | ||||
| def create_expiry_ledger_entry(expire_allocation): | ||||
| def create_expiry_ledger_entry(allocations): | ||||
| 	''' Create ledger entry for expired allocation ''' | ||||
| 	for allocation in expire_allocation: | ||||
| 	for allocation in allocations: | ||||
| 		if allocation.is_carry_forward: | ||||
| 			expire_carried_forward_allocation(allocation) | ||||
| 		else: | ||||
| @ -138,7 +138,7 @@ def get_remaining_leaves(allocation): | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def expire_allocation(allocation, expiry_date=None): | ||||
| 	''' expires allocation ''' | ||||
| 	''' expires non-carry forwarded allocation ''' | ||||
| 	leaves = get_remaining_leaves(allocation) | ||||
| 	expiry_date = expiry_date if expiry_date else allocation.to_date | ||||
| 
 | ||||
| @ -146,6 +146,7 @@ def expire_allocation(allocation, expiry_date=None): | ||||
| 		args = dict( | ||||
| 			leaves=flt(leaves) * -1, | ||||
| 			transaction_name=allocation.name, | ||||
| 			transaction_type='Leave Allocation', | ||||
| 			from_date=expiry_date, | ||||
| 			to_date=expiry_date, | ||||
| 			is_carry_forward=0, | ||||
|  | ||||
| @ -22,7 +22,7 @@ class LeavePeriod(Document): | ||||
| 
 | ||||
| 		condition_str = " and " + " and ".join(conditions) if len(conditions) else "" | ||||
| 
 | ||||
| 		employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}" | ||||
| 		employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}" #nosec | ||||
| 			.format(condition=condition_str), tuple(values))) | ||||
| 
 | ||||
| 		return employees | ||||
|  | ||||
| @ -318,7 +318,7 @@ def create_earned_leave_ledger_entry(allocation, earned_leaves, date): | ||||
| 	''' Create leave ledger entry based on the earned leave frequency ''' | ||||
| 	allocation.new_leaves_allocated = earned_leaves | ||||
| 	allocation.from_date = date | ||||
| 	allocation.carry_forwarded_leaves = 0 | ||||
| 	allocation.unused_leaves = 0 | ||||
| 	allocation.create_leave_ledger_entry() | ||||
| 
 | ||||
| def check_frequency_hit(from_date, to_date, frequency): | ||||
|  | ||||
| @ -13,11 +13,22 @@ def execute(): | ||||
| 	if frappe.db.a_row_exists("Leave Ledger Entry"): | ||||
| 		return | ||||
| 
 | ||||
| 	if not frappe.get_meta("Leave Allocation").has_field("unused_leaves"): | ||||
| 		frappe.reload_doc("HR", "doctype", "Leave Allocation") | ||||
| 		update_leave_allocation_fieldname() | ||||
| 
 | ||||
| 	generate_allocation_ledger_entries() | ||||
| 	generate_application_leave_ledger_entries() | ||||
| 	generate_encashment_leave_ledger_entries() | ||||
| 	generate_expiry_allocation_ledger_entries() | ||||
| 
 | ||||
| def update_leave_allocation_fieldname(): | ||||
| 	''' maps data from old field to the new field ''' | ||||
| 	frappe.db.sql(""" | ||||
| 		UPDATE `tabLeave Allocation` | ||||
| 		SET `unused_leaves` = `carry_forwarded_leaves` | ||||
| 	""") | ||||
| 
 | ||||
| def generate_allocation_ledger_entries(): | ||||
| 	''' fix ledger entries for missing leave allocation transaction ''' | ||||
| 	allocation_list = get_allocation_records() | ||||
| @ -64,7 +75,7 @@ def get_allocation_records(): | ||||
| 			employee, | ||||
| 			leave_type, | ||||
| 			new_leaves_allocated, | ||||
| 			carry_forwarded_leaves, | ||||
| 			unused_leaves, | ||||
| 			from_date, | ||||
| 			to_date, | ||||
| 			carry_forward | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user