package com.ruoyi.approve.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
|
import com.ruoyi.approve.bean.dto.VehicleBorrowRecordDto;
|
import com.ruoyi.approve.bean.vo.VehicleBorrowRecordVo;
|
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
|
import com.ruoyi.approve.mapper.VehicleBorrowRecordMapper;
|
import com.ruoyi.approve.mapper.VehicleMapper;
|
import com.ruoyi.approve.pojo.ApprovalTemplate;
|
import com.ruoyi.approve.pojo.Vehicle;
|
import com.ruoyi.approve.pojo.VehicleBorrowRecord;
|
import com.ruoyi.approve.service.ApprovalInstanceService;
|
import com.ruoyi.approve.service.VehicleBorrowRecordService;
|
import com.ruoyi.basic.dto.StorageBlobDTO;
|
import com.ruoyi.basic.enums.ApplicationTypeEnum;
|
import com.ruoyi.basic.enums.RecordTypeEnum;
|
import com.ruoyi.basic.utils.FileUtil;
|
import com.ruoyi.common.enums.TypeEnums;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.OrderUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.framework.security.LoginUser;
|
import com.ruoyi.project.system.domain.SysDept;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysDeptMapper;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.time.LocalDateTime;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Locale;
|
|
/**
|
* 车辆借出记录 Service 实现
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class VehicleBorrowRecordServiceImpl extends ServiceImpl<VehicleBorrowRecordMapper, VehicleBorrowRecord> implements VehicleBorrowRecordService {
|
|
private static final String BORROW_STATUS_DRAFT = "DRAFT";
|
private static final String BORROW_STATUS_IN_APPROVAL = "IN_APPROVAL";
|
private static final String BORROW_STATUS_BORROWING = "BORROWING";
|
private static final String BORROW_STATUS_RETURNED = "RETURNED";
|
private static final String BORROW_STATUS_REJECTED = "REJECTED";
|
private static final String VEHICLE_STATUS_IDLE = "IDLE";
|
|
private static final String EXTEND_STATUS_NONE = "NONE";
|
private static final String EXTEND_STATUS_PENDING = "PENDING";
|
private static final String EXTEND_STATUS_APPROVED = "APPROVED";
|
private static final String EXTEND_STATUS_REJECTED = "REJECTED";
|
|
private final VehicleBorrowRecordMapper vehicleBorrowRecordMapper;
|
private final VehicleMapper vehicleMapper;
|
private final SysDeptMapper sysDeptMapper;
|
private final ApprovalTemplateMapper approvalTemplateMapper;
|
private final ApprovalInstanceService approvalInstanceService;
|
private final FileUtil fileUtil;
|
|
@Override
|
public IPage<VehicleBorrowRecordVo> listPage(Page<VehicleBorrowRecordVo> page, VehicleBorrowRecordDto record) {
|
return vehicleBorrowRecordMapper.listPage(page, record);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean add(VehicleBorrowRecordDto record) {
|
validateBorrowRecord(record, false);
|
Vehicle vehicle = getAvailableVehicle(record.getVehicleId());
|
fillApplicantInfo(record);
|
record.setBorrowNo(OrderUtils.countTodayByCreateTime(
|
vehicleBorrowRecordMapper,
|
"CLJC",
|
"borrow_no",
|
record.getCreateTime() != null ? record.getCreateTime() : LocalDateTime.now()
|
));
|
record.setVehiclePlateNumber(vehicle.getPlateNumber());
|
record.setBorrowStatus(normalizeBorrowStatus(record.getBorrowStatus()));
|
record.setExtendStatus(EXTEND_STATUS_NONE);
|
record.setDeleted(0);
|
boolean saved = this.save(record);
|
if (!saved || record.getId() == null) {
|
throw new ServiceException("新增车辆借出记录失败");
|
}
|
saveBorrowAttachments(record.getId(), record.getBorrowStorageBlobDTOs());
|
if (BORROW_STATUS_IN_APPROVAL.equals(record.getBorrowStatus())) {
|
startApproval(record, TypeEnums.VEHICLE_BORROW_APPROVAL.getCode());
|
}
|
return true;
|
}
|
|
@Override
|
public VehicleBorrowRecord detail(Long id) {
|
if (id == null) {
|
return null;
|
}
|
return this.getOne(
|
new LambdaQueryWrapper<VehicleBorrowRecord>()
|
.eq(VehicleBorrowRecord::getId, id)
|
.eq(VehicleBorrowRecord::getDeleted, 0)
|
.last("LIMIT 1")
|
);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean update(VehicleBorrowRecordDto record) {
|
validateBorrowRecord(record, true);
|
if (record.getId() == null) {
|
throw new ServiceException("借出记录ID不能为空");
|
}
|
VehicleBorrowRecord existing = detail(record.getId());
|
if (existing == null) {
|
throw new ServiceException("借出记录不存在");
|
}
|
if (!BORROW_STATUS_DRAFT.equals(existing.getBorrowStatus())
|
&& !BORROW_STATUS_REJECTED.equals(existing.getBorrowStatus())) {
|
throw new ServiceException("当前状态的借出记录不允许修改");
|
}
|
Vehicle vehicle = getAvailableVehicle(record.getVehicleId());
|
fillApplicantInfo(record);
|
record.setVehiclePlateNumber(vehicle.getPlateNumber());
|
record.setBorrowStatus(normalizeBorrowStatus(record.getBorrowStatus()));
|
if (record.getExtendStatus() == null) {
|
record.setExtendStatus(existing.getExtendStatus());
|
}
|
record.setApprovalInstanceId(existing.getApprovalInstanceId());
|
record.setExtendApprovalInstanceId(existing.getExtendApprovalInstanceId());
|
record.setDeleted(existing.getDeleted());
|
boolean updated = this.updateById(record);
|
if (!updated) {
|
return false;
|
}
|
if (record.getBorrowStorageBlobDTOs() != null) {
|
saveBorrowAttachments(record.getId(), record.getBorrowStorageBlobDTOs());
|
}
|
if (BORROW_STATUS_IN_APPROVAL.equals(record.getBorrowStatus())) {
|
if (existing.getApprovalInstanceId() != null) {
|
approvalInstanceService.delete(Collections.singletonList(existing.getApprovalInstanceId()));
|
}
|
startApproval(record, TypeEnums.VEHICLE_BORROW_APPROVAL.getCode());
|
}
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean delete(List<Long> ids) {
|
if (ids == null || ids.isEmpty()) {
|
return false;
|
}
|
long activeCount = this.count(
|
Wrappers.<VehicleBorrowRecord>lambdaQuery()
|
.in(VehicleBorrowRecord::getId, ids)
|
.eq(VehicleBorrowRecord::getDeleted, 0)
|
.in(VehicleBorrowRecord::getBorrowStatus, BORROW_STATUS_IN_APPROVAL, BORROW_STATUS_BORROWING)
|
);
|
if (activeCount > 0) {
|
throw new ServiceException("审批中或借出中的记录不允许删除");
|
}
|
int rows = vehicleBorrowRecordMapper.update(
|
null,
|
Wrappers.<VehicleBorrowRecord>lambdaUpdate()
|
.in(VehicleBorrowRecord::getId, ids)
|
.eq(VehicleBorrowRecord::getDeleted, 0)
|
.set(VehicleBorrowRecord::getDeleted, 1)
|
);
|
return rows > 0;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean returnVehicle(VehicleBorrowRecordDto record) {
|
if (record == null || record.getId() == null) {
|
throw new ServiceException("借出记录ID不能为空");
|
}
|
VehicleBorrowRecord existing = detail(record.getId());
|
if (existing == null) {
|
throw new ServiceException("借出记录不存在");
|
}
|
if (!BORROW_STATUS_BORROWING.equals(existing.getBorrowStatus())) {
|
throw new ServiceException("只有借出中的车辆才能归还");
|
}
|
if (EXTEND_STATUS_PENDING.equals(existing.getExtendStatus()) || existing.getExtendApprovalInstanceId() != null) {
|
throw new ServiceException("延期审批中的记录不允许直接归还");
|
}
|
LocalDateTime now = record.getActualReturnTime() != null ? record.getActualReturnTime() : LocalDateTime.now();
|
VehicleBorrowRecord update = new VehicleBorrowRecord();
|
update.setId(existing.getId());
|
update.setActualReturnTime(now);
|
update.setReturnedTime(now);
|
update.setBorrowStatus(BORROW_STATUS_RETURNED);
|
update.setUpdateUser(SecurityUtils.getUserId());
|
update.setUpdateTime(now);
|
update.setExtendStatus(existing.getExtendStatus());
|
int rows = vehicleBorrowRecordMapper.updateById(update);
|
if (rows != 1) {
|
throw new ServiceException("归还车辆失败");
|
}
|
saveReturnAttachments(existing.getId(), record.getReturnStorageBlobDTOs());
|
Vehicle vehicle = new Vehicle();
|
vehicle.setId(existing.getVehicleId());
|
vehicle.setStatus("IDLE");
|
vehicleMapper.updateById(vehicle);
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean delay(VehicleBorrowRecordDto record) {
|
if (record == null || record.getId() == null) {
|
throw new ServiceException("借出记录ID不能为空");
|
}
|
if (record.getExtendTargetReturnTime() == null) {
|
throw new ServiceException("延期后的归还时间不能为空");
|
}
|
VehicleBorrowRecord existing = detail(record.getId());
|
if (existing == null) {
|
throw new ServiceException("借出记录不存在");
|
}
|
if (!BORROW_STATUS_BORROWING.equals(existing.getBorrowStatus())) {
|
throw new ServiceException("只有借出中的车辆才能申请延期");
|
}
|
if (EXTEND_STATUS_PENDING.equals(existing.getExtendStatus()) || existing.getExtendApprovalInstanceId() != null) {
|
throw new ServiceException("已有延期审批中的申请,请勿重复提交");
|
}
|
if (existing.getPlannedReturnTime() != null
|
&& !record.getExtendTargetReturnTime().isAfter(existing.getPlannedReturnTime())) {
|
throw new ServiceException("延期后的归还时间必须晚于当前计划归还时间");
|
}
|
VehicleBorrowRecord update = new VehicleBorrowRecord();
|
update.setId(existing.getId());
|
update.setExtendReason(record.getExtendReason());
|
update.setExtendTargetReturnTime(record.getExtendTargetReturnTime());
|
update.setExtendStatus(EXTEND_STATUS_PENDING);
|
update.setUpdateUser(SecurityUtils.getUserId());
|
update.setUpdateTime(LocalDateTime.now());
|
int rows = vehicleBorrowRecordMapper.updateById(update);
|
if (rows != 1) {
|
throw new ServiceException("保存延期申请失败");
|
}
|
VehicleBorrowRecord refreshed = detail(existing.getId());
|
startApproval(refreshed, TypeEnums.VEHICLE_DELAY_APPROVAL.getCode());
|
return true;
|
}
|
|
private void validateBorrowRecord(VehicleBorrowRecord record, boolean ignoreId) {
|
if (record == null) {
|
throw new ServiceException("借出记录不能为空");
|
}
|
if (!ignoreId && record.getId() != null) {
|
throw new ServiceException("新增借出记录不允许传入ID");
|
}
|
if (record.getVehicleId() == null) {
|
throw new ServiceException("请选择车辆");
|
}
|
if (record.getBorrowStartTime() == null) {
|
throw new ServiceException("借出开始时间不能为空");
|
}
|
if (record.getPlannedReturnTime() == null) {
|
throw new ServiceException("计划归还时间不能为空");
|
}
|
if (!record.getPlannedReturnTime().isAfter(record.getBorrowStartTime())) {
|
throw new ServiceException("计划归还时间必须晚于借出开始时间");
|
}
|
if (!StringUtils.hasText(record.getBorrowStatus())) {
|
record.setBorrowStatus(BORROW_STATUS_DRAFT);
|
}
|
String normalized = normalizeBorrowStatus(record.getBorrowStatus());
|
if (normalized == null) {
|
throw new ServiceException("借出状态只支持 DRAFT 或 IN_APPROVAL");
|
}
|
record.setBorrowStatus(normalized);
|
if (StringUtils.hasText(record.getExtendStatus())) {
|
String extendStatus = record.getExtendStatus().trim().toUpperCase(Locale.ROOT);
|
if (!EXTEND_STATUS_NONE.equals(extendStatus)
|
&& !EXTEND_STATUS_PENDING.equals(extendStatus)
|
&& !EXTEND_STATUS_APPROVED.equals(extendStatus)
|
&& !EXTEND_STATUS_REJECTED.equals(extendStatus)) {
|
throw new ServiceException("延期状态不合法");
|
}
|
}
|
}
|
|
private Vehicle getAvailableVehicle(Long vehicleId) {
|
Vehicle vehicle = vehicleMapper.selectOne(
|
new LambdaQueryWrapper<Vehicle>()
|
.eq(Vehicle::getId, vehicleId)
|
.eq(Vehicle::getDeleted, 0)
|
.last("LIMIT 1")
|
);
|
if (vehicle == null) {
|
throw new ServiceException("车辆不存在");
|
}
|
long activeBorrowCount = this.count(
|
Wrappers.<VehicleBorrowRecord>lambdaQuery()
|
.eq(VehicleBorrowRecord::getVehicleId, vehicleId)
|
.eq(VehicleBorrowRecord::getDeleted, 0)
|
.in(VehicleBorrowRecord::getBorrowStatus, BORROW_STATUS_IN_APPROVAL, BORROW_STATUS_BORROWING)
|
);
|
if (activeBorrowCount > 0) {
|
throw new ServiceException("当前车辆已有借出记录,不能重复借出");
|
}
|
if (!VEHICLE_STATUS_IDLE.equals(vehicle.getStatus())) {
|
throw new ServiceException("当前车辆不在可借出状态");
|
}
|
return vehicle;
|
}
|
|
private void fillApplicantInfo(VehicleBorrowRecord record) {
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
if (loginUser == null || loginUser.getUser() == null) {
|
throw new ServiceException("请先登录");
|
}
|
SysUser user = loginUser.getUser();
|
record.setApplicantId(user.getUserId());
|
record.setApplicantName(user.getNickName());
|
record.setApplicantDeptId(user.getDeptId());
|
if (user.getDeptId() != null) {
|
SysDept dept = sysDeptMapper.selectById(user.getDeptId());
|
record.setApplicantDeptName(dept != null ? dept.getDeptName() : null);
|
}
|
}
|
|
private void startApproval(VehicleBorrowRecord record, Long businessType) {
|
Long templateId = null;
|
if (record instanceof VehicleBorrowRecordDto) {
|
templateId = ((VehicleBorrowRecordDto) record).getApprovalTemplateId();
|
}
|
ApprovalTemplate approvalTemplate = resolveApprovalTemplate(templateId, businessType);
|
ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
|
approvalInstanceDto.setTemplateId(approvalTemplate.getId());
|
approvalInstanceDto.setTemplateName(approvalTemplate.getTemplateName());
|
approvalInstanceDto.setBusinessId(record.getId());
|
approvalInstanceDto.setBusinessType(businessType);
|
approvalInstanceDto.setTitle(buildApprovalTitle(record, businessType));
|
approvalInstanceDto.setApplicantId(record.getApplicantId());
|
approvalInstanceDto.setApplicantName(record.getApplicantName());
|
approvalInstanceDto.setApplyTime(LocalDateTime.now());
|
approvalInstanceDto.setStatus("PENDING");
|
approvalInstanceDto.setCurrentLevel(1);
|
|
boolean saved = approvalInstanceService.add(approvalInstanceDto);
|
if (!saved || approvalInstanceDto.getId() == null) {
|
throw new ServiceException("发起车辆审批失败");
|
}
|
|
VehicleBorrowRecord update = new VehicleBorrowRecord();
|
update.setId(record.getId());
|
if (TypeEnums.VEHICLE_BORROW_APPROVAL.getCode().equals(businessType)) {
|
update.setApprovalInstanceId(approvalInstanceDto.getId());
|
update.setBorrowStatus(BORROW_STATUS_IN_APPROVAL);
|
} else if (TypeEnums.VEHICLE_DELAY_APPROVAL.getCode().equals(businessType)) {
|
update.setExtendApprovalInstanceId(approvalInstanceDto.getId());
|
update.setExtendStatus(EXTEND_STATUS_PENDING);
|
}
|
int rows = vehicleBorrowRecordMapper.updateById(update);
|
if (rows != 1) {
|
throw new ServiceException("回填审批实例失败");
|
}
|
}
|
|
private ApprovalTemplate resolveApprovalTemplate(Long templateId, Long businessType) {
|
if (templateId != null) {
|
ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectById(templateId);
|
if (approvalTemplate == null || !Integer.valueOf(0).equals(approvalTemplate.getDeleted())) {
|
throw new ServiceException("审批模板不存在");
|
}
|
if (approvalTemplate.getEnabled() == null || approvalTemplate.getEnabled() == 0) {
|
throw new ServiceException("审批模板未启用");
|
}
|
if (approvalTemplate.getBusinessType() != null && !approvalTemplate.getBusinessType().equals(businessType)) {
|
throw new ServiceException("审批模板类型与当前业务不匹配");
|
}
|
return approvalTemplate;
|
}
|
ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne(
|
Wrappers.<ApprovalTemplate>lambdaQuery()
|
.eq(ApprovalTemplate::getBusinessType, businessType)
|
.eq(ApprovalTemplate::getEnabled, (byte) 1)
|
.eq(ApprovalTemplate::getDeleted, 0)
|
.orderByDesc(ApprovalTemplate::getId)
|
.last("LIMIT 1")
|
);
|
if (approvalTemplate == null) {
|
throw new ServiceException("请先配置车辆审批模板");
|
}
|
return approvalTemplate;
|
}
|
|
@Override
|
public void saveBorrowAttachments(Long recordId, List<StorageBlobDTO> storageBlobDTOs) {
|
if (recordId == null || recordId <= 0) {
|
return;
|
}
|
if (storageBlobDTOs == null) {
|
return;
|
}
|
fileUtil.saveStorageAttachmentByRecordTypeAndRecordId(
|
ApplicationTypeEnum.FILE.getType(),
|
RecordTypeEnum.VEHICLE_BORROW_RECORD,
|
recordId,
|
storageBlobDTOs
|
);
|
}
|
|
@Override
|
public void saveReturnAttachments(Long recordId, List<StorageBlobDTO> storageBlobDTOs) {
|
if (recordId == null || recordId <= 0) {
|
return;
|
}
|
if (storageBlobDTOs == null) {
|
return;
|
}
|
fileUtil.saveStorageAttachmentByRecordTypeAndRecordId(
|
ApplicationTypeEnum.FILE.getType(),
|
RecordTypeEnum.VEHICLE_RETURN_RECORD,
|
recordId,
|
storageBlobDTOs
|
);
|
}
|
|
private String buildApprovalTitle(VehicleBorrowRecord record, Long businessType) {
|
if (TypeEnums.VEHICLE_BORROW_APPROVAL.getCode().equals(businessType)) {
|
return "车辆借出申请:" + record.getBorrowNo();
|
}
|
if (TypeEnums.VEHICLE_DELAY_APPROVAL.getCode().equals(businessType)) {
|
return "车辆延期申请:" + record.getBorrowNo();
|
}
|
return "车辆审批:" + record.getBorrowNo();
|
}
|
|
private String normalizeBorrowStatus(String borrowStatus) {
|
if (!StringUtils.hasText(borrowStatus)) {
|
return BORROW_STATUS_DRAFT;
|
}
|
String normalized = borrowStatus.trim().toUpperCase(Locale.ROOT);
|
if (BORROW_STATUS_DRAFT.equals(normalized)
|
|| BORROW_STATUS_IN_APPROVAL.equals(normalized)
|
|| BORROW_STATUS_BORROWING.equals(normalized)
|
|| BORROW_STATUS_RETURNED.equals(normalized)
|
|| BORROW_STATUS_REJECTED.equals(normalized)) {
|
return normalized;
|
}
|
return null;
|
}
|
}
|