Skip to content

Commit

Permalink
Merge pull request #2754 from frappe/version-14-hotfix
Browse files Browse the repository at this point in the history
chore: release v14
  • Loading branch information
asmitahase authored Feb 4, 2025
2 parents e081f62 + e76856d commit 356c6db
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 50 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}

- name: Upload coverage data
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: github.event_name != 'pull_request'
with:
name: coverage-${{ matrix.container }}
Expand All @@ -140,7 +140,7 @@ jobs:
uses: actions/checkout@v2

- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4

- name: Upload coverage data
uses: codecov/codecov-action@v2
Expand Down
5 changes: 3 additions & 2 deletions hrms/hr/doctype/attendance/attendance.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@
"label": "Attendance Date",
"oldfieldname": "attendance_date",
"oldfieldtype": "Date",
"reqd": 1
"reqd": 1,
"search_index": 1
},
{
"fetch_from": "employee.company",
Expand Down Expand Up @@ -207,7 +208,7 @@
"idx": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-04-05 20:55:02.905452",
"modified": "2025-01-31 11:45:54.846562",
"modified_by": "Administrator",
"module": "HR",
"name": "Attendance",
Expand Down
58 changes: 27 additions & 31 deletions hrms/hr/doctype/attendance/attendance.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,42 +228,38 @@ def unlink_attendance_from_checkins(self):

@frappe.whitelist()
def get_events(start, end, filters=None):
from frappe.desk.reportview import get_filters_cond

events = []

employee = frappe.db.get_value("Employee", {"user_id": frappe.session.user})

if not employee:
return events

conditions = get_filters_cond("Attendance", filters, [])
add_attendance(events, start, end, conditions=conditions)
add_holidays(events, start, end, employee)
return events

return []
if isinstance(filters, str):
import json

def add_attendance(events, start, end, conditions=None):
query = """select name, attendance_date, status, employee_name
from `tabAttendance` where
attendance_date between %(from_date)s and %(to_date)s
and docstatus < 2"""
filters = json.loads(filters)
if not filters:
filters = []
filters.append(["attendance_date", "between", [get_datetime(start).date(), get_datetime(end).date()]])
attendance_records = add_attendance(filters)
add_holidays(attendance_records, start, end, employee)
return attendance_records

if conditions:
query += conditions

for d in frappe.db.sql(query, {"from_date": start, "to_date": end}, as_dict=True):
e = {
"name": d.name,
"doctype": "Attendance",
"start": d.attendance_date,
"end": d.attendance_date,
"title": f"{d.employee_name}: {cstr(d.status)}",
"status": d.status,
"docstatus": d.docstatus,
}
if e not in events:
events.append(e)
def add_attendance(filters):
attendance = frappe.get_list(
"Attendance",
fields=[
"name",
"'Attendance' as doctype",
"attendance_date as start",
"attendance_date as end",
"employee_name",
"status",
"docstatus",
],
filters=filters,
)
for record in attendance:
record["title"] = f"{record.employee_name} : {record.status}"
return attendance


def add_holidays(events, start, end, employee=None):
Expand Down
13 changes: 11 additions & 2 deletions hrms/hr/doctype/leave_allocation/test_earned_leaves.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,14 @@ def test_alloc_based_on_joining_date(self):

# assignment created on the last day of the current month
frappe.flags.current_date = get_last_day(getdate())

leave_policy_assignments = make_policy_assignment(self.employee, assignment_based_on="Joining Date")
"""set end date while making assignment based on Joining date because while start date is fetched from
employee master, make_policy_assignment ends up taking current date as end date if not specified which
causes the date of assignment to be later than the end date of leave period"""
start_date = self.employee.date_of_joining
end_date = get_last_day(add_months(self.employee.date_of_joining, 12))
leave_policy_assignments = make_policy_assignment(
self.employee, assignment_based_on="Joining Date", start_date=start_date, end_date=end_date
)
leaves_allocated = get_allocated_leaves(leave_policy_assignments[0])
effective_from = frappe.db.get_value(
"Leave Policy Assignment", leave_policy_assignments[0], "effective_from"
Expand Down Expand Up @@ -563,6 +569,7 @@ def make_policy_assignment(
rounding=0.5,
earned_leave_frequency="Monthly",
start_date=None,
end_date=None,
annual_allocation=12,
carry_forward=0,
assignment_based_on="Leave Period",
Expand All @@ -582,6 +589,8 @@ def make_policy_assignment(
"leave_policy": leave_policy.name,
"leave_period": leave_period.name,
"carry_forward": carry_forward,
"effective_from": start_date,
"effective_to": end_date,
}

leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
Expand Down
1 change: 1 addition & 0 deletions hrms/hr/doctype/leave_encashment/test_leave_encashment.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def get_encashment_created_after_leave_period(self, employee, is_carry_forward):
"Salary Structure for Encashment",
"Monthly",
employee,
from_date=start_date,
other_details={"leave_encashment_amount_per_day": 50},
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def set_dates(self):
)
elif self.assignment_based_on == "Joining Date":
self.effective_from = frappe.db.get_value("Employee", self.employee, "date_of_joining")
if not self.effective_to:
self.effective_to = get_last_day(add_months(self.effective_from, 12))

def validate_policy_assignment_overlap(self):
leave_policy_assignments = frappe.get_all(
Expand Down Expand Up @@ -132,12 +134,13 @@ def get_new_leaves(self, annual_allocation, leave_details, date_of_joining):
from frappe.model.meta import get_field_precision

precision = get_field_precision(frappe.get_meta("Leave Allocation").get_field("new_leaves_allocated"))

current_date = getdate(frappe.flags.current_date) or getdate()
# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
if leave_details.is_compensatory:
new_leaves_allocated = 0
# if earned leave is being allcated after the effective period, then let them be calculated pro-rata

elif leave_details.is_earned_leave:
elif leave_details.is_earned_leave and current_date < getdate(self.effective_to):
new_leaves_allocated = self.get_leaves_for_passed_months(
annual_allocation, leave_details, date_of_joining
)
Expand All @@ -162,7 +165,7 @@ def get_leaves_for_passed_months(self, annual_allocation, leave_details, date_of
from hrms.hr.utils import get_monthly_earned_leave

def _get_current_and_from_date():
current_date = frappe.flags.current_date or getdate()
current_date = getdate(frappe.flags.current_date) or getdate()
if current_date > getdate(self.effective_to):
current_date = getdate(self.effective_to)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_months, get_first_day, get_year_ending, getdate
from frappe.utils import add_days, add_months, get_first_day, get_year_ending, get_year_start, getdate

from hrms.hr.doctype.leave_application.test_leave_application import get_employee, get_leave_period
from hrms.hr.doctype.leave_period.test_leave_period import create_leave_period
Expand Down Expand Up @@ -33,6 +33,9 @@ def setUp(self):
self.original_doj = employee.date_of_joining
self.employee = employee

def tearDown(self):
frappe.db.set_value("Employee", self.employee.name, "date_of_joining", self.original_doj)

def test_grant_leaves(self):
leave_period = get_leave_period()
leave_policy = create_leave_policy(annual_allocation=10)
Expand Down Expand Up @@ -208,5 +211,58 @@ def test_pro_rated_leave_allocation_for_custom_date_range(self):

self.assertGreater(new_leaves_allocated, 0)

def tearDown(self):
frappe.db.set_value("Employee", self.employee.name, "date_of_joining", self.original_doj)
def test_earned_leave_allocation_if_leave_policy_assignment_submitted_after_period(self):
year_start_date = get_year_start(getdate())
year_end_date = get_year_ending(getdate())
leave_period = create_leave_period(year_start_date, year_end_date)

# assignment 10 days after the leave period
frappe.flags.current_date = add_days(year_end_date, 10)
leave_type = create_leave_type(
leave_type_name="_Test Earned Leave", is_earned_leave=True, allocate_on_day="Last Day"
)
annual_earned_leaves = 10
leave_policy = create_leave_policy(leave_type=leave_type, annual_allocation=annual_earned_leaves)
leave_policy.submit()

data = {
"assignment_based_on": "Leave Period",
"leave_policy": leave_policy.name,
"leave_period": leave_period.name,
}
assignment = create_assignment(self.employee.name, frappe._dict(data))
assignment.submit()

earned_leave_allocation = frappe.get_value(
"Leave Allocation", {"leave_policy_assignment": assignment.name}, "new_leaves_allocated"
)
self.assertEqual(earned_leave_allocation, annual_earned_leaves)

def test_earned_leave_allocation_for_leave_period_spanning_two_years(self):
first_year_start_date = get_year_start(getdate())
second_year_end_date = get_year_ending(add_months(first_year_start_date, 12))
leave_period = create_leave_period(first_year_start_date, second_year_end_date)

# assignment during mid second year
frappe.flags.current_date = add_months(second_year_end_date, -6)
leave_type = create_leave_type(
leave_type_name="_Test Earned Leave", is_earned_leave=True, allocate_on_day="Last Day"
)
annual_earned_leaves = 24
leave_policy = create_leave_policy(leave_type=leave_type, annual_allocation=annual_earned_leaves)
leave_policy.submit()

data = {
"assignment_based_on": "Leave Period",
"leave_policy": leave_policy.name,
"leave_period": leave_period.name,
}
assignment = create_assignment(self.employee.name, frappe._dict(data))
assignment.submit()

earned_leave_allocation = frappe.get_value(
"Leave Allocation", {"leave_policy_assignment": assignment.name}, "new_leaves_allocated"
)
# months passed (18) are calculated correctly but total allocation of 36 exceeds 24 hence 24
# this upper cap is intentional, without that 36 leaves would be allocated correctly
self.assertEqual(earned_leave_allocation, 24)
9 changes: 6 additions & 3 deletions hrms/payroll/doctype/salary_slip/salary_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -865,10 +865,14 @@ def compute_income_tax_breakup(self):

if hasattr(self, "total_structured_tax_amount") and hasattr(self, "current_structured_tax_amount"):
self.future_income_tax_deductions = (
self.total_structured_tax_amount - self.income_tax_deducted_till_date
self.total_structured_tax_amount
+ self.get("full_tax_on_additional_earnings", 0)
- self.income_tax_deducted_till_date
)

self.current_month_income_tax = self.current_structured_tax_amount
self.current_month_income_tax = self.current_structured_tax_amount + self.get(
"full_tax_on_additional_earnings", 0
)

# non included current_month_income_tax separately as its already considered
# while calculating income_tax_deducted_till_date
Expand All @@ -882,7 +886,6 @@ def compute_ctc(self):
+ self.current_structured_taxable_earnings_before_exemption
+ self.future_structured_taxable_earnings_before_exemption
+ self.current_additional_earnings
+ self.other_incomes
+ self.unclaimed_taxable_benefits
+ self.non_taxable_earnings
)
Expand Down
10 changes: 6 additions & 4 deletions hrms/payroll/doctype/salary_slip/test_salary_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,9 @@ def test_statistical_component_based_on_payment_days(self):
precision = entry.precision("amount")
break

self.assertEqual(amount, flt((1000 * ss.payment_days / ss.total_working_days) * 0.5, precision))
self.assertEqual(
amount, flt(flt((1000 * ss.payment_days / ss.total_working_days), precision) * 0.5, precision)
)

def make_activity_for_employee(self):
activity_type = frappe.get_doc("Activity Type", "_Test Activity Type")
Expand Down Expand Up @@ -1416,14 +1418,14 @@ def test_income_tax_breakup_fields(self):

monthly_tax_amount = 11403.6

self.assertEqual(salary_slip.ctc, 1226000.0)
self.assertEqual(salary_slip.ctc, 1216000.0)
self.assertEqual(salary_slip.income_from_other_sources, 10000.0)
self.assertEqual(salary_slip.non_taxable_earnings, 10000.0)
self.assertEqual(salary_slip.total_earnings, 1236000.0)
self.assertEqual(salary_slip.total_earnings, 1226000.0)
self.assertEqual(salary_slip.standard_tax_exemption_amount, 50000.0)
self.assertEqual(salary_slip.tax_exemption_declaration, 100000.0)
self.assertEqual(salary_slip.deductions_before_tax_calculation, 2400.0)
self.assertEqual(salary_slip.annual_taxable_amount, 1073600.0)
self.assertEqual(salary_slip.annual_taxable_amount, 1063600.0)
self.assertEqual(flt(salary_slip.income_tax_deducted_till_date, 2), monthly_tax_amount)
self.assertEqual(flt(salary_slip.current_month_income_tax, 2), monthly_tax_amount)
self.assertEqual(flt(salary_slip.future_income_tax_deductions, 2), 125439.65)
Expand Down

0 comments on commit 356c6db

Please sign in to comment.