package cn.iocoder.yudao.module.hrm.service.attendance;
|
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceClockReqVO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRuleDO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO;
|
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
|
import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceRecordMapper;
|
import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.*;
|
|
class HrmAttendanceClockLocationTest {
|
|
private final HrmAttendanceRecordServiceImpl service = new HrmAttendanceRecordServiceImpl();
|
|
private HrmAttendanceRuleDO requiredRule() {
|
return HrmAttendanceRuleDO.builder().locationRequired(true).locationName("公司前台")
|
.longitude(BigDecimal.ZERO).latitude(BigDecimal.ZERO)
|
.radiusMeters(100).coordinateSystem("WGS84").build();
|
}
|
|
private HrmAttendanceClockReqVO position(String latitude, String accuracy) {
|
HrmAttendanceClockReqVO reqVO = new HrmAttendanceClockReqVO();
|
reqVO.setLongitude(BigDecimal.ZERO);
|
reqVO.setLatitude(new BigDecimal(latitude));
|
reqVO.setAccuracy(new BigDecimal(accuracy));
|
reqVO.setCoordinateSystem("WGS84");
|
return reqVO;
|
}
|
|
@Test
|
void oldRuleWithoutLocationStillAcceptsClock() {
|
HrmAttendanceRuleDO rule = HrmAttendanceRuleDO.builder().locationRequired(false).build();
|
assertNull(service.validateClockLocation(rule, null));
|
assertNull(service.validateClockLocation(rule, position("0.0001", "20")).distanceMeters());
|
}
|
|
@Test
|
void requiredLocationValidatesCompletenessCoordinatesAndAccuracy() {
|
HrmAttendanceRuleDO rule = requiredRule();
|
assertThrows(ServiceException.class, () -> service.validateClockLocation(rule, null));
|
assertThrows(ServiceException.class, () -> service.validateClockLocation(rule, position("91", "20")));
|
assertThrows(ServiceException.class, () -> service.validateClockLocation(rule, position("0", "100.01")));
|
assertNotNull(service.validateClockLocation(rule, position("0", "100")));
|
}
|
|
@Test
|
void comparesUnroundedDistanceWithRadius() {
|
HrmAttendanceRuleDO rule = requiredRule();
|
assertTrue(HrmAttendanceRecordServiceImpl.haversineMeters(0, 0, 0, 0.00089) < 100);
|
assertNotNull(service.validateClockLocation(rule, position("0.00089", "20")));
|
assertThrows(ServiceException.class, () -> service.validateClockLocation(rule, position("0.00091", "20")));
|
}
|
|
@Test
|
void invalidClockOutLocationDoesNotCreateMissingClockInRecord() {
|
HrmAttendanceHolidayService holidayService = mock(HrmAttendanceHolidayService.class);
|
HrmEmployeeService employeeService = mock(HrmEmployeeService.class);
|
HrmAttendanceRuleService ruleService = mock(HrmAttendanceRuleService.class);
|
HrmAttendanceRecordMapper mapper = mock(HrmAttendanceRecordMapper.class);
|
ReflectionTestUtils.setField(service, "attendanceHolidayService", holidayService);
|
ReflectionTestUtils.setField(service, "employeeService", employeeService);
|
ReflectionTestUtils.setField(service, "attendanceRuleService", ruleService);
|
ReflectionTestUtils.setField(service, "attendanceRecordMapper", mapper);
|
LocalDateTime clockTime = LocalDateTime.of(2026, 10, 22, 18, 56);
|
when(holidayService.isWorkDay(any(LocalDate.class))).thenReturn(true);
|
HrmEmployeeDO employee = HrmEmployeeDO.builder().id(1L).deptId(2L).build();
|
when(employeeService.getEmployee(1L)).thenReturn(employee);
|
when(ruleService.getAttendanceRuleByDeptId(2L)).thenReturn(requiredRule());
|
assertThrows(ServiceException.class,
|
() -> service.clockOut(1L, clockTime, position("0.00091", "20"), null));
|
verify(mapper, never()).insert(any(HrmAttendanceRecordDO.class));
|
verify(mapper, never()).updateById(any(HrmAttendanceRecordDO.class));
|
}
|
}
|