package org.dromara.qa.md.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import org.dromara.common.core.utils.DateUtils;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.qa.md.domain.bo.BatchCalibrateBo;
|
import org.dromara.qa.md.domain.bo.BatchConfigBo;
|
import org.dromara.qa.md.domain.CalibrationRecord;
|
import org.dromara.qa.md.domain.WeighingBox;
|
import org.dromara.qa.md.mapper.WeighingBoxMapper;
|
import org.dromara.qa.md.service.ICalibrationRecordService;
|
import org.dromara.qa.md.service.IWeighingBoxService;
|
import org.dromara.qa.md.service.INotificationService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* 称重盒子服务实现
|
*
|
* @author ruoyi
|
* @date 2026-04-09
|
*/
|
@Service
|
public class WeighingBoxServiceImpl extends ServiceImpl<WeighingBoxMapper, WeighingBox> implements IWeighingBoxService
|
{
|
@Autowired
|
private WeighingBoxMapper weighingBoxMapper;
|
|
@Autowired
|
private ICalibrationRecordService calibrationRecordService;
|
|
@Autowired
|
private INotificationService notificationService;
|
|
@Override
|
public TableDataInfo<WeighingBox> queryPageList(WeighingBox weighingBox, PageQuery pageQuery) {
|
// 检查是否需要按校准状态过滤
|
if (weighingBox.getCalibStatus() != null && !weighingBox.getCalibStatus().isEmpty()) {
|
// 使用带校准状态过滤的查询
|
long total = weighingBoxMapper.selectWeighingBoxCountWithCalibStatus(weighingBox);
|
List<WeighingBox> records = weighingBoxMapper.selectWeighingBoxListWithCalibStatus(weighingBox);
|
|
// 手动分页
|
int pageNum = pageQuery.getPageNum();
|
int pageSize = pageQuery.getPageSize();
|
int start = (pageNum - 1) * pageSize;
|
int end = Math.min(start + pageSize, records.size());
|
List<WeighingBox> pageRecords = start < records.size() ? records.subList(start, end) : new ArrayList<>();
|
|
// 计算每个盒子的校准状态(保持与前端一致)
|
for (WeighingBox box : pageRecords) {
|
calculateCalibStatus(box);
|
}
|
|
// 构建返回结果
|
TableDataInfo<WeighingBox> tableDataInfo = new TableDataInfo<>();
|
tableDataInfo.setRows(pageRecords);
|
tableDataInfo.setTotal(total);
|
tableDataInfo.setCode(200);
|
tableDataInfo.setMsg("查询成功");
|
return tableDataInfo;
|
} else {
|
// 使用常规分页查询
|
Page<WeighingBox> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
|
|
// 构建查询条件
|
LambdaQueryWrapper<WeighingBox> queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
|
queryWrapper.eq(WeighingBox::getDelFlag, 0);
|
|
if (weighingBox.getName() != null && !weighingBox.getName().isEmpty()) {
|
queryWrapper.like(WeighingBox::getName, weighingBox.getName())
|
.or().like(WeighingBox::getCode, weighingBox.getName())
|
.or().like(WeighingBox::getDescription, weighingBox.getName())
|
.or().like(WeighingBox::getLocation, weighingBox.getName());
|
}
|
if (weighingBox.getActiveStatus() != null) {
|
queryWrapper.eq(WeighingBox::getActiveStatus, weighingBox.getActiveStatus());
|
}
|
|
queryWrapper.orderByDesc(WeighingBox::getCreateTime);
|
|
// 执行分页查询
|
Page<WeighingBox> resultPage = baseMapper.selectPage(page, queryWrapper);
|
|
// 计算每个盒子的校准状态
|
for (WeighingBox box : resultPage.getRecords()) {
|
calculateCalibStatus(box);
|
}
|
|
return TableDataInfo.build(resultPage);
|
}
|
}
|
|
@Override
|
public List<WeighingBox> selectWeighingBoxList(WeighingBox weighingBox)
|
{
|
List<WeighingBox> list = weighingBoxMapper.selectWeighingBoxList(weighingBox);
|
for (WeighingBox box : list)
|
{
|
calculateCalibStatus(box);
|
}
|
return list;
|
}
|
|
@Override
|
public int insertWeighingBox(WeighingBox weighingBox)
|
{
|
// 计算下次校准日期
|
if (weighingBox.getLastCalibDate() != null && weighingBox.getCalibCycleDays() != null)
|
{
|
Date nextCalibDate = DateUtils.addDays(weighingBox.getLastCalibDate(), weighingBox.getCalibCycleDays());
|
weighingBox.setNextCalibDate(nextCalibDate);
|
}
|
return baseMapper.insert(weighingBox);
|
}
|
|
@Override
|
public int updateWeighingBox(WeighingBox weighingBox)
|
{
|
// 计算下次校准日期
|
if (weighingBox.getLastCalibDate() != null && weighingBox.getCalibCycleDays() != null)
|
{
|
Date nextCalibDate = DateUtils.addDays(weighingBox.getLastCalibDate(), weighingBox.getCalibCycleDays());
|
weighingBox.setNextCalibDate(nextCalibDate);
|
}
|
return baseMapper.updateById(weighingBox);
|
}
|
|
@Override
|
public int deleteWeighingBoxByIds(Long[] boxIds)
|
{
|
return baseMapper.deleteBatchIds(Arrays.asList(boxIds));
|
}
|
|
@Override
|
@Transactional
|
public int calibrate(Long boxId, Date calibDate, BigDecimal actualWeight, String note)
|
{
|
WeighingBox box = baseMapper.selectById(boxId);
|
if (box == null)
|
{
|
return 0;
|
}
|
|
// 保存校准前的状态
|
Date prevCalibDate = box.getLastCalibDate();
|
|
// 更新盒子信息
|
box.setLastCalibDate(calibDate);
|
box.setNextCalibDate(DateUtils.addDays(calibDate, box.getCalibCycleDays()));
|
baseMapper.updateById(box);
|
|
// 计算偏差
|
BigDecimal deviation = null;
|
BigDecimal deviationPct = null;
|
if (actualWeight != null)
|
{
|
deviation = actualWeight.subtract(box.getWeight());
|
if (box.getWeight().compareTo(BigDecimal.ZERO) > 0)
|
{
|
deviationPct = deviation.divide(box.getWeight(), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
}
|
}
|
|
// 创建校准记录
|
CalibrationRecord record = new CalibrationRecord();
|
record.setTargetType("weighing_box");
|
record.setTargetId(boxId);
|
record.setTargetCode(box.getCode());
|
record.setTargetName(box.getName());
|
record.setCalibDate(calibDate);
|
record.setCalibCycleDays(box.getCalibCycleDays());
|
record.setStandardWeight(box.getWeight());
|
record.setActualWeight(actualWeight);
|
record.setDeviation(deviation);
|
record.setDeviationPct(deviationPct);
|
record.setPrevCalibDate(prevCalibDate);
|
record.setNextCalibDate(box.getNextCalibDate());
|
record.setOperator("admin"); // 实际应该从当前用户获取
|
record.setNote(note);
|
record.setCreateTime(new Date());
|
calibrationRecordService.save(record);
|
|
return 1;
|
}
|
|
@Override
|
@Transactional
|
public Map<String, Object> batchCalibrate(BatchCalibrateBo batchCalibrateDTO)
|
{
|
List<Long> boxIds = batchCalibrateDTO.getBoxIds();
|
Date calibDate = batchCalibrateDTO.getCalibDate();
|
String note = batchCalibrateDTO.getNote();
|
List<BatchCalibrateBo.CalibrateItem> items = batchCalibrateDTO.getItems();
|
|
Map<Long, BigDecimal> actualWeightMap = new HashMap<>();
|
if (items != null)
|
{
|
for (BatchCalibrateBo.CalibrateItem item : items)
|
{
|
actualWeightMap.put(item.getBoxId(), item.getActualWeight());
|
}
|
}
|
|
String batchId = UUID.randomUUID().toString();
|
List<CalibrationRecord> records = new ArrayList<>();
|
List<Map<String, Object>> results = new ArrayList<>();
|
|
for (Long boxId : boxIds)
|
{
|
WeighingBox box = baseMapper.selectById(boxId);
|
if (box == null)
|
{
|
continue;
|
}
|
|
// 保存校准前的状态
|
Date prevCalibDate = box.getLastCalibDate();
|
|
// 更新盒子信息
|
box.setLastCalibDate(calibDate);
|
box.setNextCalibDate(DateUtils.addDays(calibDate, box.getCalibCycleDays()));
|
baseMapper.updateById(box);
|
|
// 计算偏差
|
BigDecimal actualWeight = actualWeightMap.get(boxId);
|
BigDecimal deviation = null;
|
BigDecimal deviationPct = null;
|
if (actualWeight != null)
|
{
|
deviation = actualWeight.subtract(box.getWeight());
|
if (box.getWeight().compareTo(BigDecimal.ZERO) > 0)
|
{
|
deviationPct = deviation.divide(box.getWeight(), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
}
|
}
|
|
// 创建校准记录
|
CalibrationRecord record = new CalibrationRecord();
|
record.setTargetType("weighing_box");
|
record.setTargetId(boxId);
|
record.setTargetCode(box.getCode());
|
record.setTargetName(box.getName());
|
record.setCalibDate(calibDate);
|
record.setCalibCycleDays(box.getCalibCycleDays());
|
record.setStandardWeight(box.getWeight());
|
record.setActualWeight(actualWeight);
|
record.setDeviation(deviation);
|
record.setDeviationPct(deviationPct);
|
record.setPrevCalibDate(prevCalibDate);
|
record.setNextCalibDate(box.getNextCalibDate());
|
record.setBatchId(batchId);
|
record.setOperator("admin"); // 实际应该从当前用户获取
|
record.setNote(note);
|
record.setCreateTime(new Date());
|
records.add(record);
|
|
// 准备返回结果
|
Map<String, Object> result = new HashMap<>();
|
result.put("boxId", boxId);
|
result.put("nextCalibDate", box.getNextCalibDate());
|
results.add(result);
|
}
|
|
// 批量插入校准记录
|
if (!records.isEmpty())
|
{
|
calibrationRecordService.batchInsert(records);
|
}
|
|
Map<String, Object> resultMap = new HashMap<>();
|
resultMap.put("successCount", boxIds.size());
|
resultMap.put("failCount", 0);
|
resultMap.put("results", results);
|
return resultMap;
|
}
|
|
@Override
|
@Transactional
|
public int batchConfig(BatchConfigBo batchConfigDTO)
|
{
|
Integer calibCycleDays = batchConfigDTO.getCalibCycleDays();
|
Integer remindDays = batchConfigDTO.getRemindDays();
|
String applyScope = batchConfigDTO.getApplyScope();
|
List<Long> boxIds = batchConfigDTO.getBoxIds();
|
|
List<Long> targetBoxIds = new ArrayList<>();
|
if ("all".equals(applyScope))
|
{
|
// 所有已启用的盒子
|
List<WeighingBox> boxes = weighingBoxMapper.selectActiveWeighingBoxes();
|
for (WeighingBox box : boxes)
|
{
|
targetBoxIds.add(box.getId());
|
}
|
}
|
else if ("selected".equals(applyScope) && boxIds != null)
|
{
|
targetBoxIds.addAll(boxIds);
|
}
|
|
if (targetBoxIds.isEmpty())
|
{
|
return 0;
|
}
|
|
// 批量更新校准配置
|
int result = weighingBoxMapper.batchUpdateCalibConfig(targetBoxIds, calibCycleDays, remindDays);
|
|
// 重新计算下次校准日期
|
for (Long boxId : targetBoxIds)
|
{
|
WeighingBox box = baseMapper.selectById(boxId);
|
if (box.getLastCalibDate() != null)
|
{
|
box.setNextCalibDate(DateUtils.addDays(box.getLastCalibDate(), calibCycleDays));
|
baseMapper.updateById(box);
|
}
|
}
|
|
return result;
|
}
|
|
@Override
|
public int batchUpdateStatus(List<Long> boxIds, Integer activeStatus)
|
{
|
return weighingBoxMapper.batchUpdateStatus(boxIds, activeStatus);
|
}
|
|
@Override
|
public Map<String, Object> copyBox(Long sourceId, Integer count)
|
{
|
WeighingBox sourceBox = baseMapper.selectById(sourceId);
|
if (sourceBox == null)
|
{
|
throw new RuntimeException("源盒子不存在");
|
}
|
Date nextCalibDate = null;
|
List<Long> newIds = new ArrayList<>();
|
List<String> newCodes = new ArrayList<>();
|
// 计算下次校准日期
|
if ( sourceBox.getCalibCycleDays() != null)
|
{
|
nextCalibDate = DateUtils.addDays(new Date(), sourceBox.getCalibCycleDays());
|
}
|
for (int i = 1; i <= count; i++)
|
{
|
WeighingBox newBox = new WeighingBox();
|
newBox.setName(sourceBox.getName() + "-" + (char)('a' + i - 1));
|
newBox.setCode(sourceBox.getCode() + "-" + (char)('a' + i - 1));
|
newBox.setWeight(sourceBox.getWeight());
|
newBox.setUnit(sourceBox.getUnit());
|
newBox.setLocation(sourceBox.getLocation());
|
newBox.setCalibCycleDays(sourceBox.getCalibCycleDays());
|
newBox.setRemindDays(sourceBox.getRemindDays());
|
newBox.setActiveStatus(sourceBox.getActiveStatus());
|
newBox.setDescription(sourceBox.getDescription());
|
newBox.setLastCalibDate(new Date());
|
newBox.setNextCalibDate(nextCalibDate);
|
newBox.setCreateBy("admin"); // 实际应该从当前用户获取
|
newBox.setCreateTime(new Date());
|
baseMapper.insert(newBox);
|
newIds.add(newBox.getId());
|
newCodes.add(newBox.getCode());
|
}
|
|
Map<String, Object> result = new HashMap<>();
|
result.put("ids", newIds);
|
result.put("codes", newCodes);
|
return result;
|
}
|
|
@Override
|
public Map<String, Integer> getStatistics()
|
{
|
Map<String, Integer> statistics = new HashMap<>();
|
statistics.put("total", Math.toIntExact(baseMapper.selectCount(null)));
|
|
// 已启用
|
int activeCount = Math.toIntExact(baseMapper.selectCount(new LambdaQueryWrapper<WeighingBox>()
|
.eq(WeighingBox::getActiveStatus, 1)
|
.eq(WeighingBox::getDelFlag, 0)));
|
statistics.put("active", activeCount);
|
|
// 已停用
|
int inactiveCount = Math.toIntExact(baseMapper.selectCount(new LambdaQueryWrapper<WeighingBox>()
|
.eq(WeighingBox::getActiveStatus, 0)
|
.eq(WeighingBox::getDelFlag, 0)));
|
statistics.put("inactive", inactiveCount);
|
|
// 校准状态统计
|
List<WeighingBox> boxes = baseMapper.selectList(new LambdaQueryWrapper<WeighingBox>()
|
.eq(WeighingBox::getDelFlag, 0)
|
.eq(WeighingBox::getActiveStatus, 1));
|
|
int normal = 0, warning = 0, overdue = 0, unset = 0;
|
for (WeighingBox box : boxes)
|
{
|
calculateCalibStatus(box);
|
String status = box.getCalibStatus();
|
if ("normal".equals(status)) normal++;
|
else if ("warning".equals(status)) warning++;
|
else if ("overdue".equals(status)) overdue++;
|
else if ("unset".equals(status)) unset++;
|
}
|
|
statistics.put("normal", normal);
|
statistics.put("warning", warning);
|
statistics.put("overdue", overdue);
|
statistics.put("unset", unset);
|
|
return statistics;
|
}
|
|
@Override
|
public WeighingBox calculateCalibStatus(WeighingBox weighingBox)
|
{
|
Date nextCalibDate = weighingBox.getNextCalibDate();
|
if (nextCalibDate == null)
|
{
|
weighingBox.setCalibStatus("unset");
|
weighingBox.setCalibDaysLeft(null);
|
return weighingBox;
|
}
|
|
long daysLeft = DateUtils.getTimeDifference(new Date(), nextCalibDate, TimeUnit.DAYS);
|
weighingBox.setCalibDaysLeft((int) daysLeft);
|
|
if (daysLeft < 0)
|
{
|
weighingBox.setCalibStatus("overdue");
|
}
|
else if (daysLeft <= weighingBox.getRemindDays())
|
{
|
weighingBox.setCalibStatus("warning");
|
}
|
else
|
{
|
weighingBox.setCalibStatus("normal");
|
}
|
|
return weighingBox;
|
}
|
}
|