liu
13 小时以前 690b713454828f34f901bc1e3a5f7bcc35a31b30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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));
    }
}