package com.xiaopeng.maintenance.service.impl;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.xiaopeng.api.model.maintenance.XpCheckLocation;
|
import com.xiaopeng.api.model.maintenance.XpClockIn;
|
import com.xiaopeng.api.model.maintenance.XpShift;
|
import com.xiaopeng.common.core.domain.R;
|
import com.xiaopeng.common.core.utils.DateUtils;
|
import com.xiaopeng.common.core.utils.GeodesyUtil;
|
import com.xiaopeng.maintenance.dto.ClockDTO;
|
import com.xiaopeng.maintenance.dto.VerifyRangeDTO;
|
import com.xiaopeng.maintenance.mapper.XpCheckLocationMapper;
|
import com.xiaopeng.maintenance.mapper.XpClockInMapper;
|
import com.xiaopeng.maintenance.mapper.XpShiftMapper;
|
import com.xiaopeng.maintenance.service.IXpClockInService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.util.List;
|
import java.util.Map;
|
import lombok.extern.slf4j.Slf4j;
|
import java.util.Objects;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.LocalTime;
|
import java.util.List;
|
|
/**
|
* <p>
|
* 打卡明细 服务实现类
|
* </p>
|
*
|
* @author mitao
|
* @since 2026-02-03
|
*/
|
@Slf4j
|
@Service
|
public class XpClockInServiceImpl extends ServiceImpl<XpClockInMapper, XpClockIn> implements IXpClockInService {
|
|
@Autowired
|
private XpCheckLocationMapper xpCheckLocationMapper;
|
@Autowired
|
private XpShiftMapper xpShiftMapper;
|
@Autowired
|
private XpClockInMapper xpClockInMapper;
|
|
@Override
|
public Boolean verifyRange(VerifyRangeDTO dto) {
|
|
XpCheckLocation xpCheckLocation = xpCheckLocationMapper.selectById(dto.getLocationId());
|
|
Map<String, Double> distance = GeodesyUtil.getDistance(dto.getUserLon()+","+dto.getUserLat(), xpCheckLocation.getLocationLon()+","+xpCheckLocation.getLocationLat());
|
if (null != distance) {
|
Double distance1 = distance.get("WGS84");
|
if (BigDecimal.valueOf(distance1).compareTo(xpCheckLocation.getLocationRange())>0) {
|
return false;
|
}else {
|
return true;
|
}
|
} else {
|
log.error("调用高德计算距离出错");
|
return false;
|
}
|
}
|
|
@Override
|
public R<String> clockIn(ClockDTO dto) {
|
|
XpCheckLocation xpCheckLocation = xpCheckLocationMapper.selectById(dto.getLocationId());
|
|
Map<String, Double> distance = GeodesyUtil.getDistance(dto.getUserLon()+","+dto.getUserLat(), xpCheckLocation.getLocationLon()+","+xpCheckLocation.getLocationLat());
|
if (null != distance) {
|
Double distance1 = distance.get("WGS84");
|
if (BigDecimal.valueOf(distance1).compareTo(xpCheckLocation.getLocationRange()) > 0) {
|
return R.fail("不在打卡范围内");
|
}
|
}else {
|
return R.fail("打卡失败");
|
}
|
|
// 查询班次
|
XpShift xpShift = xpShiftMapper.selectById(dto.getShiftId());
|
if (null == xpShift) {
|
return R.fail("班次不存在");
|
}
|
// 开始打卡时间
|
String startTime = xpShift.getStartTime();
|
LocalDateTime startLocalDateTime = DateUtils.stringToLocalDateTime(LocalDate.now() + " " + startTime + ":00");
|
|
XpClockIn xpClockIn = new XpClockIn();
|
xpClockIn.setAppUserId(dto.getOperationsUserId());
|
xpClockIn.setClockInTime(LocalDateTime.now());
|
xpClockIn.setClockInLon(dto.getUserLon());
|
xpClockIn.setClockInLat(dto.getUserLat());
|
xpClockIn.setShiftId(dto.getShiftId());
|
xpClockIn.setClockInAddress(dto.getClockInAddress());
|
if (xpClockIn.getClockInTime().isAfter(startLocalDateTime)) {
|
xpClockIn.setClockInResult(2);
|
}else {
|
xpClockIn.setClockInResult(1);
|
}
|
this.save(xpClockIn);
|
return R.ok();
|
}
|
|
@Override
|
public R<String> clockOut(ClockDTO dto) {
|
|
XpCheckLocation xpCheckLocation = xpCheckLocationMapper.selectById(dto.getLocationId());
|
Map<String, Double> distance = GeodesyUtil.getDistance(dto.getUserLon()+","+dto.getUserLat(), xpCheckLocation.getLocationLon()+","+xpCheckLocation.getLocationLat());
|
if (null != distance) {
|
Double distance1 = distance.get("WGS84");
|
if (BigDecimal.valueOf(distance1).compareTo(xpCheckLocation.getLocationRange()) > 0) {
|
return R.fail("不在打卡范围内");
|
}
|
}else {
|
return R.fail("打卡失败");
|
}
|
|
// 查询上班打卡信息
|
XpClockIn xpClockIn = xpClockInMapper.selectOne(Wrappers.lambdaQuery(XpClockIn.class)
|
.eq(XpClockIn::getAppUserId, dto.getOperationsUserId())
|
.likeRight(XpClockIn::getClockInTime, LocalDate.now())
|
.last("LIMIT 1"));
|
if(Objects.isNull(xpClockIn)){
|
return R.fail("请先上班打卡");
|
}
|
|
// 查询班次
|
XpShift xpShift = xpShiftMapper.selectById(xpClockIn.getShiftId());
|
if (null == xpShift) {
|
return R.fail("班次不存在");
|
}
|
// 开始打卡时间
|
String endTime = xpShift.getEndTime();
|
LocalDateTime endLocalDateTime = DateUtils.stringToLocalDateTime(LocalDate.now() + " " + endTime + ":00");
|
|
xpClockIn.setClockOutTime(LocalDateTime.now());
|
xpClockIn.setClockOutLon(dto.getUserLon());
|
xpClockIn.setClockOutLat(dto.getUserLat());
|
xpClockIn.setClockOutAddress(dto.getClockOutAddress());
|
if (xpClockIn.getClockOutTime().isBefore(endLocalDateTime)) {
|
xpClockIn.setClockInResult(2);
|
}else {
|
xpClockIn.setClockInResult(1);
|
}
|
this.updateById(xpClockIn);
|
return R.ok();
|
}
|
@Override
|
public Boolean checkWorkStatus(Long appUserId) {
|
if (appUserId == null) {
|
log.warn("检查上班状态失败: appUserId 为空");
|
return false;
|
}
|
|
try {
|
// 1. 计算当天时间范围
|
LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN); // 00:00:00
|
LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); // 23:59:59
|
|
// 2. 查询当天打卡记录
|
List<XpClockIn> records = baseMapper.selectTodayClockInRecords(
|
appUserId, startTime, endTime
|
);
|
|
// 3. 判断上班状态
|
if (records == null || records.isEmpty()) {
|
// 无打卡记录 = 未上班
|
log.debug("用户 {} 今日无打卡记录, workFlag=false", appUserId);
|
return false;
|
} else if (records.size() == 1) {
|
// 1条记录 = 已上班未下班
|
log.debug("用户 {} 今日打卡1次, workFlag=true", appUserId);
|
return true;
|
} else {
|
// 2条及以上记录 = 已下班
|
log.debug("用户 {} 今日打卡{}次, workFlag=false", appUserId, records.size());
|
return false;
|
}
|
|
} catch (Exception e) {
|
log.error("检查用户上班状态异常, appUserId={}", appUserId, e);
|
// 异常情况返回 false
|
return false;
|
}
|
}
|
}
|