Skip to content

Commit bcadce5

Browse files
authored
Merge pull request #3923 from frappe/version-15-hotfix
2 parents beba403 + 4674a46 commit bcadce5

4 files changed

Lines changed: 75 additions & 6 deletions

File tree

hrms/hr/doctype/leave_application/leave_application.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ frappe.ui.form.on("Leave Application", {
291291
});
292292
$(".form-message").prop("hidden", true);
293293
},
294+
posting_date: function (frm) {
295+
frm.trigger("make_dashboard");
296+
frm.trigger("get_leave_balance");
297+
},
294298
});
295299

296300
frappe.tour["Leave Application"] = [

hrms/hr/doctype/leave_application/leave_application.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ def on_submit(self):
111111
self.notify_employee()
112112

113113
self.create_leave_ledger_entry()
114+
# create a reverse ledger entry for backdated leave applications for whom expiry entry already exists
115+
leave_allocation = self.get_leave_allocation()
116+
if not leave_allocation:
117+
return
118+
to_date = leave_allocation.get("to_date")
119+
can_expire = not frappe.db.get_value("Leave Type", self.leave_type, "is_carry_forward")
120+
121+
if to_date < getdate() and can_expire:
122+
args = frappe._dict(
123+
leaves=self.total_leave_days, from_date=to_date, to_date=to_date, is_carry_forward=0
124+
)
125+
create_leave_ledger_entry(self, args)
126+
114127
self.reload()
115128

116129
def before_cancel(self):
@@ -247,6 +260,22 @@ def validate_back_dated_application(self):
247260
).format(formatdate(future_allocation[0].from_date), future_allocation[0].name)
248261
)
249262

263+
def get_leave_allocation(self):
264+
date = self.posting_date or getdate()
265+
LeaveAllocation = frappe.qb.DocType("Leave Allocation")
266+
leave_allocation = (
267+
frappe.qb.from_(LeaveAllocation)
268+
.select(LeaveAllocation.to_date)
269+
.where(
270+
((LeaveAllocation.from_date <= date) & (date <= LeaveAllocation.to_date))
271+
& (LeaveAllocation.docstatus == 1)
272+
& (LeaveAllocation.leave_type == self.leave_type)
273+
& (LeaveAllocation.employee == self.employee)
274+
)
275+
).run(as_dict=True)
276+
277+
return leave_allocation[0] if leave_allocation else None
278+
250279
def update_attendance(self):
251280
if self.status != "Approved":
252281
return
@@ -969,12 +998,12 @@ def get_leave_balance_on(
969998

970999
allocation_records = get_leave_allocation_records(employee, date, leave_type)
9711000
allocation = allocation_records.get(leave_type, frappe._dict())
972-
973-
end_date = allocation.to_date if cint(consider_all_leaves_in_the_allocation_period) else date
1001+
end_date = (
1002+
allocation.to_date if (allocation and cint(consider_all_leaves_in_the_allocation_period)) else date
1003+
)
9741004
cf_expiry = get_allocation_expiry_for_cf_leaves(employee, leave_type, to_date, allocation.from_date)
9751005

9761006
leaves_taken = get_leaves_for_period(employee, leave_type, allocation.from_date, end_date)
977-
9781007
manually_expired_leaves = get_manually_expired_leaves(
9791008
employee, leave_type, allocation.from_date, end_date
9801009
)
@@ -1138,7 +1167,7 @@ def get_manually_expired_leaves(
11381167
& (ledger.employee == employee)
11391168
& (ledger.leave_type == leave_type)
11401169
& (ledger.from_date >= from_date)
1141-
& (ledger.to_date <= end_date)
1170+
& (ledger.to_date < end_date)
11421171
& (ledger.transaction_type == "Leave Allocation")
11431172
& ((ledger.is_expired == 1) & (ledger.is_carry_forward == 0))
11441173
)

hrms/hr/doctype/leave_application/test_leave_application.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1404,11 +1404,45 @@ def test_leave_balance_when_allocation_is_expired_manually(self):
14041404
expire_allocation(leave_allocation, expiry_date=getdate())
14051405

14061406
leave_balance = get_leave_balance_on(
1407-
employee=employee.name, leave_type=leave_type.name, date=getdate()
1407+
employee=employee.name,
1408+
leave_type=leave_type.name,
1409+
date=getdate(),
1410+
consider_all_leaves_in_the_allocation_period=True,
14081411
)
14091412

14101413
self.assertEqual(leave_balance, 0)
14111414

1415+
def test_backdated_application_after_expiry(self):
1416+
employee = get_employee().name
1417+
previous_month_start = get_first_day(add_months(getdate(), -1))
1418+
previous_month_end = get_last_day(previous_month_start)
1419+
leave_type = create_leave_type(leave_type_name="_Test_backdated_application").name
1420+
allocation = make_allocation_record(
1421+
employee, leave_type, previous_month_start, previous_month_end, leaves=10
1422+
)
1423+
expire_allocation(allocation, expiry_date=previous_month_end)
1424+
doc = frappe.new_doc(
1425+
"Leave Application",
1426+
employee=employee,
1427+
leave_type=leave_type,
1428+
from_date=previous_month_start,
1429+
to_date=previous_month_start,
1430+
posting_date=previous_month_end,
1431+
status="Approved",
1432+
)
1433+
doc.save()
1434+
doc.submit()
1435+
self.assertEqual(get_leave_balance_on(employee, leave_type, previous_month_end), 9)
1436+
leave_ledger_entry = frappe.get_all(
1437+
"Leave Ledger Entry",
1438+
fields="*",
1439+
filters={"transaction_name": doc.name},
1440+
order_by="leaves",
1441+
)
1442+
self.assertEqual(len(leave_ledger_entry), 2)
1443+
self.assertEqual(leave_ledger_entry[0].leaves, doc.total_leave_days * -1)
1444+
self.assertEqual(leave_ledger_entry[1].leaves, doc.total_leave_days * 1)
1445+
14121446

14131447
def create_carry_forwarded_allocation(employee, leave_type, date=None):
14141448
date = date or nowdate()

hrms/hr/report/employee_birthday/test_employee_birthday.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
from erpnext.setup.doctype.employee.test_employee import make_employee
66

7+
from hrms.hr.doctype.staffing_plan.test_staffing_plan import make_company
78
from hrms.hr.report.employee_birthday.employee_birthday import execute
89

910

1011
class TestEmployeeBirthday(FrappeTestCase):
1112
def setUp(self):
12-
self.company = "_Test Company"
13+
make_company(name="_New Test Company", abbr="_NTC")
14+
self.company = "_New Test Company"
1315
self.birthdate = getdate().replace(year=1990)
1416

1517
def test_employee_birth_day_report(self):

0 commit comments

Comments
 (0)