feat(UX): Option to exclude holidays while marking monthly attendance (#29185)

diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 7dcfac2..b1eaaf8 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -5,9 +5,9 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import cstr, formatdate, get_datetime, getdate, nowdate
+from frappe.utils import cint, cstr, formatdate, get_datetime, getdate, nowdate
 
-from erpnext.hr.utils import validate_active_employee
+from erpnext.hr.utils import get_holiday_dates_for_employee, validate_active_employee
 
 
 class Attendance(Document):
@@ -171,7 +171,7 @@
 		})
 
 @frappe.whitelist()
-def get_unmarked_days(employee, month):
+def get_unmarked_days(employee, month, exclude_holidays=0):
 	import calendar
 	month_map = get_month_map()
 
@@ -191,6 +191,11 @@
 	])
 
 	marked_days = [get_datetime(record.attendance_date) for record in records]
+	if cint(exclude_holidays):
+		holiday_dates = get_holiday_dates_for_employee(employee, month_start, month_end)
+		holidays = [get_datetime(record) for record in holiday_dates]
+		marked_days.extend(holidays)
+
 	unmarked_days = []
 
 	for date in dates_of_month:
diff --git a/erpnext/hr/doctype/attendance/attendance_list.js b/erpnext/hr/doctype/attendance/attendance_list.js
index 6b3c29a..3a5c591 100644
--- a/erpnext/hr/doctype/attendance/attendance_list.js
+++ b/erpnext/hr/doctype/attendance/attendance_list.js
@@ -28,6 +28,7 @@
 					onchange: function() {
 						dialog.set_df_property("unmarked_days", "hidden", 1);
 						dialog.set_df_property("status", "hidden", 1);
+						dialog.set_df_property("exclude_holidays", "hidden", 1);
 						dialog.set_df_property("month", "value", '');
 						dialog.set_df_property("unmarked_days", "options", []);
 						dialog.no_unmarked_days_left = false;
@@ -42,9 +43,14 @@
 					onchange: function() {
 						if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
 							dialog.set_df_property("status", "hidden", 0);
+							dialog.set_df_property("exclude_holidays", "hidden", 0);
 							dialog.set_df_property("unmarked_days", "options", []);
 							dialog.no_unmarked_days_left = false;
-							me.get_multi_select_options(dialog.fields_dict.employee.value, dialog.fields_dict.month.value).then(options => {
+							me.get_multi_select_options(
+								dialog.fields_dict.employee.value,
+								dialog.fields_dict.month.value,
+								dialog.fields_dict.exclude_holidays.get_value()
+							).then(options => {
 								if (options.length > 0) {
 									dialog.set_df_property("unmarked_days", "hidden", 0);
 									dialog.set_df_property("unmarked_days", "options", options);
@@ -65,6 +71,31 @@
 
 				},
 				{
+					label: __("Exclude Holidays"),
+					fieldtype: "Check",
+					fieldname: "exclude_holidays",
+					hidden: 1,
+					onchange: function() {
+						if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
+							dialog.set_df_property("status", "hidden", 0);
+							dialog.set_df_property("unmarked_days", "options", []);
+							dialog.no_unmarked_days_left = false;
+							me.get_multi_select_options(
+								dialog.fields_dict.employee.value,
+								dialog.fields_dict.month.value,
+								dialog.fields_dict.exclude_holidays.get_value()
+							).then(options => {
+								if (options.length > 0) {
+									dialog.set_df_property("unmarked_days", "hidden", 0);
+									dialog.set_df_property("unmarked_days", "options", options);
+								} else {
+									dialog.no_unmarked_days_left = true;
+								}
+							});
+						}
+					}
+				},
+				{
 					label: __("Unmarked Attendance for days"),
 					fieldname: "unmarked_days",
 					fieldtype: "MultiCheck",
@@ -105,7 +136,7 @@
 		});
 	},
 
-	get_multi_select_options: function(employee, month) {
+	get_multi_select_options: function(employee, month, exclude_holidays) {
 		return new Promise(resolve => {
 			frappe.call({
 				method: 'erpnext.hr.doctype.attendance.attendance.get_unmarked_days',
@@ -113,6 +144,7 @@
 				args: {
 					employee: employee,
 					month: month,
+					exclude_holidays: exclude_holidays
 				}
 			}).then(r => {
 				var options = [];