@@ -117,9 +117,7 @@ def test_skip_attendance_on_leave(self):
117117 self .to_date = get_year_ending (getdate ())
118118
119119 frappe .delete_doc_if_exists ("Leave Type" , "Test Skip Attendance" , force = 1 )
120- leave_type = frappe .get_doc (
121- dict (leave_type_name = "Test Skip Attendance" , doctype = "Leave Type" )
122- ).insert ()
120+ leave_type = frappe .get_doc (leave_type_name = "Test Skip Attendance" , doctype = "Leave Type" ).insert ()
123121
124122 make_allocation_record (leave_type = leave_type .name , from_date = self .from_date , to_date = self .to_date )
125123 today = getdate ()
@@ -243,6 +241,99 @@ def test_half_day_status_change_when_existing_attendance_is_updated(self):
243241 )
244242 self .assertEqual (half_day_status , "Absent" )
245243
244+ def test_half_day_absent_half_to_present (self ):
245+ """Test attendance request updates half_day_status from Absent to Present when existing Half Day attendance has the other half marked absent"""
246+ today = getdate ()
247+
248+ mark_attendance (self .employee .name , today , "Half Day" , half_day_status = "Absent" )
249+
250+ attendance_request = frappe .get_doc (
251+ {
252+ "doctype" : "Attendance Request" ,
253+ "employee" : self .employee .name ,
254+ "from_date" : today ,
255+ "to_date" : today ,
256+ "reason" : "On Duty" ,
257+ "half_day" : 1 ,
258+ "half_day_date" : today ,
259+ "company" : "_Test Company" ,
260+ }
261+ ).save ()
262+ attendance_request .submit ()
263+
264+ updated = frappe .db .get_value (
265+ "Attendance" ,
266+ {"employee" : self .employee .name , "attendance_date" : today , "docstatus" : 1 },
267+ ["status" , "half_day_status" ],
268+ as_dict = True ,
269+ )
270+ self .assertEqual (updated .status , "Half Day" )
271+ self .assertEqual (updated .half_day_status , "Present" )
272+
273+ def test_half_day_with_shift_auto_absent (self ):
274+ """Test half-day attendance request when shift_type auto-flags the other half as absent due to missing checkins"""
275+ from_date = get_year_start (add_months (getdate (), - 1 ))
276+ to_date = get_year_ending (getdate ())
277+ today = getdate ()
278+
279+ frappe .delete_doc_if_exists ("Leave Type" , "Test Half Day Leave" , force = 1 )
280+ leave_type = frappe .get_doc (leave_type_name = "Test Half Day Leave" , doctype = "Leave Type" ).insert ()
281+ make_allocation_record (leave_type = leave_type .name , from_date = from_date , to_date = to_date )
282+ frappe .db .delete ("Holiday" , {"parent" : self .holiday_list })
283+
284+ # 1) Submit half-day leave
285+ leave_application = frappe .get_doc (
286+ {
287+ "doctype" : "Leave Application" ,
288+ "employee" : self .employee .name ,
289+ "leave_type" : leave_type .name ,
290+ "from_date" : today ,
291+ "to_date" : today ,
292+ "half_day" : 1 ,
293+ "half_day_date" : today ,
294+ "status" : "Approved" ,
295+ }
296+ ).insert ()
297+ leave_application .submit ()
298+
299+ # 2) Create shift type + assignment
300+ shift_type = create_shift ("Test Half Day Shift" , "09:00:00" , "17:00:00" )
301+ shift_type .process_attendance_after = add_days (today , - 1 )
302+ shift_type .last_sync_of_checkin = add_days (today , 1 )
303+ shift_type .enable_auto_attendance = 1
304+ shift_type .save ()
305+ create_shift_assignment (self .employee .name , shift_type .name , add_days (today , - 1 ), add_days (today , 1 ))
306+
307+ # 3) Attendance request for the other half — creates half-day attendance
308+ attendance_request = frappe .get_doc (
309+ {
310+ "doctype" : "Attendance Request" ,
311+ "employee" : self .employee .name ,
312+ "from_date" : today ,
313+ "to_date" : today ,
314+ "reason" : "On Duty" ,
315+ "half_day" : 1 ,
316+ "half_day_date" : today ,
317+ "company" : "_Test Company" ,
318+ }
319+ ).save ()
320+ attendance_request .submit ()
321+
322+ # 4) Shift auto-attendance marks the other half absent when no checkins exist
323+ frappe .get_doc ("Shift Type" , shift_type .name ).mark_absent_for_half_day_dates (self .employee .name )
324+
325+ # Verify
326+ attendance = frappe .db .get_value (
327+ "Attendance" ,
328+ {"attendance_request" : attendance_request .name },
329+ ["name" , "status" , "half_day_status" , "modify_half_day_status" ],
330+ as_dict = True ,
331+ )
332+ self .assertTrue (attendance )
333+ self .assertEqual (attendance .status , "Half Day" )
334+ self .assertEqual (attendance .half_day_status , "Absent" )
335+ self .assertEqual (attendance .modify_half_day_status , 0 )
336+
246337 @HRMSTestSuite .change_settings ("HR Settings" , {"allow_multiple_shift_assignments" : True })
247338 def test_overlap_with_different_shifts (self ):
248339 shift_1 = create_shift ("Morning Shift" , "08:00:00" , "12:00:00" )
0 commit comments