Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 103 additions & 3 deletions employee_self_service/mobile/v1/attendance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
get_holiday_list_for_employee,
)
from frappe import _
from frappe.utils import cint, getdate
from frappe.utils import add_days, cint, date_diff, flt, getdate, today

from employee_self_service.mobile.v1.api_utils import (
convert_timezone,
Expand Down Expand Up @@ -154,7 +154,6 @@ def get_ess_calendar_details(year=None, month=None):
attendance_data = build_attendance_data(
year, month, days_in_month, attendance_records, holidays
)

return gen_response(
200, "ESS calendar data fetched successfully", attendance_data
)
Expand All @@ -179,7 +178,7 @@ def get_attendance_records(employee, start_date, end_date):
def get_employee_holidays(employee, start_date, end_date):
"""Fetch holiday dates for a given employee and date range."""
holiday_list = get_holiday_list_for_employee(employee, raise_exception=False)

frappe.log_error(title="holi",message=holiday_list)
if not holiday_list:
return set()

Expand Down Expand Up @@ -213,3 +212,104 @@ def build_attendance_data(year, month, days_in_month, attendance_records, holida
attendance_data[date_str] = "Holiday" if date in holidays else "No Record"

return attendance_data


def _get_attendance_summary(employee, year, month):
"""
Compute present/absent/days-off counts for a given month using the same
data sources as get_ess_calendar_details (attendance records + holiday list).

Returns a dict in the same shape as get_attendance_details in ess.py.
"""
days_in_month = monthrange(year, month)[1]
month_start = getdate(f"{year}-{month:02d}-01")
month_end = getdate(f"{year}-{month:02d}-{days_in_month}")
yesterday = getdate(add_days(today(), -1))

if yesterday < month_start:
till_date_days = 0
elif yesterday > month_end:
till_date_days = days_in_month
else:
till_date_days = date_diff(yesterday, month_start) + 1

present_count = flt(0)
leave_count = flt(0)
holidays_till_date = flt(0)

if till_date_days > 0:
till_date = min(yesterday, month_end)

attendance_records = get_attendance_records(
employee,
month_start.strftime("%Y-%m-%d"),
month_end.strftime("%Y-%m-%d"),
)
holidays = get_employee_holidays(
employee,
month_start.strftime("%Y-%m-%d"),
month_end.strftime("%Y-%m-%d"),
)

for record in attendance_records:
record_date = getdate(record["attendance_date"])
if record_date > till_date:
continue
status = record["status"]
if status in ("Present", "Work From Home"):
present_count += 1
elif status == "Half Day":
present_count += 0.5
leave_count += 0.5
elif status == "On Leave":
leave_count += 1

holidays_till_date = flt(sum(1 for h in holidays if h <= till_date))

days_off = leave_count + holidays_till_date
absent = max(flt(0), flt(till_date_days) - present_count - days_off)

return {
"month_title": month_start.strftime("%B"),
"data": [
{"type": "Total Days", "data": [till_date_days, days_in_month]},
{"type": "Presents", "data": [present_count, till_date_days]},
{"type": "Absents", "data": [absent, till_date_days]},
{"type": "Days off", "data": [days_off, till_date_days]},
],
}


@frappe.whitelist()
def get_attendance_details_dashboard():
"""Current-month attendance summary for the dashboard."""
try:
emp_data = get_employee_by_user(frappe.session.user, fields=["name", "company"])
if not emp_data:
return gen_response(404, "Employee not found")
today_date = getdate(today())
summary = _get_attendance_summary(emp_data["name"], today_date.year, today_date.month)
return gen_response(200, "Attendance data get successfully", summary)
except Exception as e:
return exception_handler(e)


@frappe.whitelist()
def get_attendance_details_by_month(year=None, month=None):
"""Attendance summary for a given year and month."""
try:
if not year or not month:
return gen_response(500, "year and month are required")

year, month = cint(year), cint(month)
today_date = getdate(today())
if (year, month) > (today_date.year, today_date.month):
return gen_response(400, "Cannot fetch attendance for a future month")

emp_data = get_employee_by_user(frappe.session.user, fields=["name", "company"])
if not emp_data:
return gen_response(404, "Employee not found")
summary = _get_attendance_summary(emp_data["name"], year, month)
return gen_response(200, "Attendance data get successfully", summary)
except Exception as e:
return exception_handler(e)
34 changes: 21 additions & 13 deletions employee_self_service/mobile/v1/ess.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
get_till_date_holiday_month_wise,
validate_employee_data,
)
from employee_self_service.mobile.v1.attendance import _get_attendance_summary
from employee_self_service.mobile.v1.task import *
from employee_self_service.mobile.v1.transactions import *
from employee_self_service.utils import add_ess_comment
Expand Down Expand Up @@ -754,14 +755,16 @@ def get_leave_balance_dashboard():
return exception_handler(e)


#moved into attendance.py file
@frappe.whitelist()
def get_attendance_details_dashboard():
try:
emp_data = get_employee_by_user(frappe.session.user, fields=["name", "company"])
attendance_details = get_attendance_details(emp_data)
return gen_response(
200, "Leave balance data get successfully", attendance_details
)
if not emp_data:
return gen_response(404, "Employee not found")
today_date = getdate()
summary = _get_attendance_summary(emp_data["name"], today_date.year, today_date.month)
return gen_response(200, "Attendance data get successfully", summary)
except Exception as e:
return exception_handler(e)

Expand Down Expand Up @@ -880,6 +883,7 @@ def get_attendance_details(emp_data, year=None, month=None):

@frappe.whitelist()
def run_attendance_report(employee, company):
from hrms.hr.report.monthly_attendance_sheet.monthly_attendance_sheet import execute
filters = {
"filter_based_on": "Month",
"month": cstr(frappe.utils.getdate().month),
Expand All @@ -888,11 +892,10 @@ def run_attendance_report(employee, company):
"employee": employee,
"summarized_view": 1,
}
from frappe.desk.query_report import run

attendance_report = run("Monthly Attendance Sheet", filters=filters)
if attendance_report.get("result"):
return attendance_report.get("result")[0]
columns, data, *_ = execute(filters)
if data:
return data[0]


def get_latest_leave(dashboard_data, employee):
Expand Down Expand Up @@ -1294,7 +1297,7 @@ def get_attendance_list(year=None, month=None):
"days_in_month": calendar.monthrange(int(year), int(month))[1],
"present": present_count,
"absent": absent_count,
"late": late_count,
"late": late_count
}
attendance_data = {
"attendance_details": attendance_details,
Expand Down Expand Up @@ -2442,14 +2445,19 @@ def get_hr_policies():
return exception_handler(e)


# moved into the attendance.py file
@frappe.whitelist()
def get_attendance_details_by_month(year, month):
try:
year, month = cint(year), cint(month)
today_date = getdate()
if (year, month) > (today_date.year, today_date.month):
return gen_response(400, "Cannot fetch attendance for a future month")
emp_data = get_employee_by_user(frappe.session.user, fields=["name", "company"])
attendance_details = get_attendance_details(emp_data, year, month)
return gen_response(
200, "Leave balance data get successfully", attendance_details
)
if not emp_data:
return gen_response(404, "Employee not found")
summary = _get_attendance_summary(emp_data["name"], year, month)
return gen_response(200, "Attendance data get successfully", summary)
except Exception as e:
return exception_handler(e)

Expand Down
Loading