l3能源成本分摊(部分完成留存)

This commit is contained in:
2025-12-07 17:23:47 +08:00
parent b6328a94da
commit 59951b77c3
100 changed files with 14350 additions and 847 deletions

View File

@@ -13,6 +13,7 @@ import com.klp.ems.domain.vo.ChainAnalysisVo;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 能耗记录Service接口
@@ -73,4 +74,25 @@ public interface IEmsEnergyConsumptionService {
/** 环比分析periodType=day/week/month/year + dateKey可过滤 */
ChainAnalysisVo getChainAnalysis(EmsEnergyConsumptionQueryBo queryBo);
/**
* 获取设备的上次抄表记录(用于自动填充起始数据)
* @param meterId 设备ID
* @return 上次抄表记录如果没有则返回null
*/
EmsEnergyConsumptionVo getLastReadingForMeter(Long meterId);
/**
* 获取设备本月的累计消耗量
* @param meterId 设备ID
* @return 本月累计消耗量如果没有则返回0
*/
Double getMonthlyConsumption(Long meterId);
/**
* 获取能耗统计信息
* @param bo 查询条件
* @return 统计信息(总记录数、总消耗量、平均消耗量、最大消耗量等)
*/
Map<String, Object> getStatistics(EmsEnergyConsumptionBo bo);
}

View File

@@ -2,7 +2,12 @@ package com.klp.ems.service;
import com.klp.ems.domain.EmsEnergyRate;
import com.klp.ems.domain.vo.EmsEnergyRateVo;
import com.klp.ems.domain.vo.EmsRateTierVo;
import com.klp.ems.domain.vo.EmsRateTimePeriodLinkVo;
import com.klp.ems.domain.bo.EmsEnergyRateBo;
import com.klp.ems.domain.bo.EmsRateTierBo;
import com.klp.ems.domain.bo.EmsRateTimePeriodLinkBo;
import com.klp.ems.domain.bo.EmsRateTierPeriodLinkBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
@@ -10,7 +15,8 @@ import java.util.Collection;
import java.util.List;
/**
* 能源费率currency 为 INT0=CNY,1=USD,2=EURService接口
* 能源费率Service接口
* 支持:固定费率、峰谷分时、阶梯电价、峰谷+阶梯组合
*
* @author Joshi
* @date 2025-09-28
@@ -18,32 +24,62 @@ import java.util.List;
public interface IEmsEnergyRateService {
/**
* 查询能源费率currency 为 INT0=CNY,1=USD,2=EUR
* 查询能源费率
*/
EmsEnergyRateVo queryById(Long energyRateId);
/**
* 查询能源费率currency 为 INT0=CNY,1=USD,2=EUR列表
* 查询能源费率列表
*/
TableDataInfo<EmsEnergyRateVo> queryPageList(EmsEnergyRateBo bo, PageQuery pageQuery);
/**
* 查询能源费率currency 为 INT0=CNY,1=USD,2=EUR列表
* 查询能源费率列表
*/
List<EmsEnergyRateVo> queryList(EmsEnergyRateBo bo);
/**
* 新增能源费率(currency 为 INT0=CNY,1=USD,2=EUR
* 新增能源费率(包括梯度和时段费率
*/
Boolean insertByBo(EmsEnergyRateBo bo);
/**
* 修改能源费率(currency 为 INT0=CNY,1=USD,2=EUR
* 修改能源费率(包括梯度和时段费率
*/
Boolean updateByBo(EmsEnergyRateBo bo);
/**
* 校验并批量删除能源费率(currency 为 INT0=CNY,1=USD,2=EUR信息
* 删除能源费率(级联删除梯度和时段费率)
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取费率的梯度费率列表
*/
List<EmsRateTierVo> getRateTiers(Long energyRateId);
/**
* 获取费率的时段费率列表
*/
List<EmsRateTimePeriodLinkVo> getRateTimePeriods(Long energyRateId);
/**
* 保存梯度费率返回保存后的梯度列表包含tierId
*/
List<EmsRateTierVo> saveTiers(Long energyRateId, List<EmsRateTierBo> tiers);
/**
* 保存时段费率
*/
Boolean saveTimePeriods(Long energyRateId, List<EmsRateTimePeriodLinkBo> timePeriods);
/**
* 获取梯度的峰谷时段费率(用于梯度+峰谷组合模式)
*/
List<EmsRateTierPeriodLinkBo> getTierPeriodLinks(Long tierId);
/**
* 保存梯度-时段关联费率(用于梯度+峰谷组合模式)
*/
Boolean saveTierPeriodLinks(Long tierId, List<EmsRateTierPeriodLinkBo> tierPeriodLinks);
}

View File

@@ -5,6 +5,8 @@ import com.klp.ems.domain.vo.EmsMeterVo;
import com.klp.ems.domain.bo.EmsMeterBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
@@ -46,4 +48,14 @@ public interface IEmsMeterService {
* 校验并批量删除计量设备(阈值移至此处)信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 下载设备导入模板
*/
void downloadTemplate(HttpServletResponse response);
/**
* 导入设备
*/
Boolean importMeters(MultipartFile file);
}

View File

@@ -0,0 +1,58 @@
package com.klp.ems.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.klp.ems.domain.EmsRateTierPeriodLink;
import com.klp.ems.domain.bo.EmsRateTierPeriodLinkBo;
import com.klp.ems.domain.vo.EmsRateTierPeriodLinkVo;
import java.util.List;
/**
* 梯度与时段关联 Service 接口
*
* @author Joshi
* @date 2025-12-05
*/
public interface IEmsRateTierPeriodLinkService extends IService<EmsRateTierPeriodLink> {
/**
* 根据梯度ID查询所有关联的时段费率
*
* @param tierId 梯度ID
* @return 梯度-时段关联列表
*/
List<EmsRateTierPeriodLink> getByTierId(Long tierId);
/**
* 根据梯度ID删除所有关联的时段费率
*
* @param tierId 梯度ID
* @return 是否删除成功
*/
Boolean deleteByTierId(Long tierId);
/**
* 根据费率ID删除所有关联的梯度-时段费率
*
* @param energyRateId 费率ID
* @return 是否删除成功
*/
Boolean deleteByEnergyRateId(Long energyRateId);
/**
* 查询梯度-时段关联的完整信息(包含梯度和时段详情)
*
* @param energyRateId 费率ID
* @return 梯度-时段关联VO列表
*/
List<EmsRateTierPeriodLinkVo> getVoByEnergyRateId(Long energyRateId);
/**
* 批量保存梯度-时段关联费率
*
* @param tierId 梯度ID
* @param tierPeriodLinks 梯度-时段关联列表
* @return 是否保存成功
*/
Boolean saveTierPeriodLinks(Long tierId, List<EmsRateTierPeriodLinkBo> tierPeriodLinks);
}

View File

@@ -0,0 +1,58 @@
package com.klp.ems.service;
import com.klp.ems.domain.vo.EmsRateTierVo;
import com.klp.ems.domain.bo.EmsRateTierBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 梯度费率Service接口
*
* @author Joshi
* @date 2025-12-05
*/
public interface IEmsRateTierService {
/**
* 查询梯度费率
*/
EmsRateTierVo queryById(Long tierId);
/**
* 查询梯度费率列表
*/
TableDataInfo<EmsRateTierVo> queryPageList(EmsRateTierBo bo, PageQuery pageQuery);
/**
* 查询梯度费率列表
*/
List<EmsRateTierVo> queryList(EmsRateTierBo bo);
/**
* 根据费率ID查询梯度费率列表
*/
List<EmsRateTierVo> queryByRateId(Long energyRateId);
/**
* 新增梯度费率
*/
Boolean insertByBo(EmsRateTierBo bo);
/**
* 修改梯度费率
*/
Boolean updateByBo(EmsRateTierBo bo);
/**
* 删除梯度费率
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据费率ID删除所有梯度费率
*/
Boolean deleteByRateId(Long energyRateId);
}

View File

@@ -0,0 +1,58 @@
package com.klp.ems.service;
import com.klp.ems.domain.vo.EmsRateTimePeriodLinkVo;
import com.klp.ems.domain.bo.EmsRateTimePeriodLinkBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 费率与时间段关联Service接口
*
* @author Joshi
* @date 2025-12-05
*/
public interface IEmsRateTimePeriodLinkService {
/**
* 查询费率与时间段关联
*/
EmsRateTimePeriodLinkVo queryById(Long linkId);
/**
* 查询费率与时间段关联列表
*/
TableDataInfo<EmsRateTimePeriodLinkVo> queryPageList(EmsRateTimePeriodLinkBo bo, PageQuery pageQuery);
/**
* 查询费率与时间段关联列表
*/
List<EmsRateTimePeriodLinkVo> queryList(EmsRateTimePeriodLinkBo bo);
/**
* 根据费率ID查询峰谷时段费率列表
*/
List<EmsRateTimePeriodLinkVo> queryByRateId(Long energyRateId);
/**
* 新增费率与时间段关联
*/
Boolean insertByBo(EmsRateTimePeriodLinkBo bo);
/**
* 修改费率与时间段关联
*/
Boolean updateByBo(EmsRateTimePeriodLinkBo bo);
/**
* 删除费率与时间段关联
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据费率ID删除所有关联
*/
Boolean deleteByRateId(Long energyRateId);
}

View File

@@ -0,0 +1,48 @@
package com.klp.ems.service;
import com.klp.ems.domain.vo.EmsTimePeriodVo;
import com.klp.ems.domain.bo.EmsTimePeriodBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 时间段Service接口
*
* @author Joshi
* @date 2025-12-05
*/
public interface IEmsTimePeriodService {
/**
* 查询时间段
*/
EmsTimePeriodVo queryById(Long periodId);
/**
* 查询时间段列表
*/
TableDataInfo<EmsTimePeriodVo> queryPageList(EmsTimePeriodBo bo, PageQuery pageQuery);
/**
* 查询时间段列表
*/
List<EmsTimePeriodVo> queryList(EmsTimePeriodBo bo);
/**
* 新增时间段
*/
Boolean insertByBo(EmsTimePeriodBo bo);
/**
* 修改时间段
*/
Boolean updateByBo(EmsTimePeriodBo bo);
/**
* 删除时间段
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,19 @@
package com.klp.ems.service;
import java.time.LocalDate;
/**
* 综合能源分摊调度/执行服务
*/
public interface IEnergyAllocationService {
/**
* 根据日期+能源类型触发一次分摊,若 energyTypeId 为空则针对所有已配置能源类型。
*/
void dispatch(LocalDate calcDate, Long energyTypeId, String allocationScope);
/**
* 将指定任务标记为需要重新计算并立即执行。
*/
void rerunTask(Long taskId);
}

View File

@@ -0,0 +1,25 @@
package com.klp.ems.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.ems.domain.bo.EnergyCostReportBo;
import com.klp.ems.domain.vo.EnergyCostSummaryVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import java.util.List;
import java.util.Map;
/**
* 能源成本报表 Service
*/
public interface IEnergyCostReportService {
/** 概览统计 */
Map<String, Object> overview(EnergyCostReportBo bo);
/** 汇总数据 */
List<EnergyCostSummaryVo> summary(EnergyCostReportBo bo);
/** 明细分页 */
TableDataInfo<WmsEnergyCoilDailyVo> detail(EnergyCostReportBo bo, PageQuery pageQuery);
}

View File

@@ -0,0 +1,42 @@
package com.klp.ems.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.ems.domain.bo.WmsEnergyCoilDailyBo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyStatisticsVo;
import java.util.Collection;
import java.util.List;
/**
* 钢卷日能源成本分摊结果 Service
*/
public interface IWmsEnergyCoilDailyService {
WmsEnergyCoilDailyVo queryById(Long energyCostId);
TableDataInfo<WmsEnergyCoilDailyVo> queryPageList(WmsEnergyCoilDailyBo bo, PageQuery pageQuery);
List<WmsEnergyCoilDailyVo> queryList(WmsEnergyCoilDailyBo bo);
/**
* 查询待操作钢卷的能源成本(基于待操作时间范围计算)
* 1. 查询所有待操作记录(已操作或等待操作的钢卷)
* 2. 按待操作的时间范围查询抄表记录
* 3. 计算该时间段内的能源消耗和成本
* 4. 按分摊方式分摊到每个钢卷
*/
TableDataInfo<WmsEnergyCoilDailyVo> queryPendingActionCoilCost(WmsEnergyCoilDailyBo bo, PageQuery pageQuery);
/**
* 查询待操作钢卷的能源成本统计
*/
WmsEnergyCoilDailyStatisticsVo queryPendingActionCoilCostStatistics(String enterCoilNo, String currentCoilNo, Long warehouseId);
Boolean insertByBo(WmsEnergyCoilDailyBo bo);
Boolean updateByBo(WmsEnergyCoilDailyBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -1,12 +1,16 @@
package com.klp.ems.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.helper.LoginHelper;
import com.klp.ems.domain.EmsEnergyType;
import com.klp.ems.domain.EmsLocation;
import com.klp.ems.domain.EmsMeter;
import com.klp.ems.domain.bo.EmsEnergyConsumptionQueryBo;
import com.klp.ems.domain.bo.MeterFilterBo;
import com.klp.ems.domain.bo.TimeRangeWithMetersBo;
@@ -15,6 +19,7 @@ import com.klp.ems.domain.vo.SummaryDailyVo;
import com.klp.ems.domain.vo.SummaryMonthlyVo;
import com.klp.ems.domain.vo.YearOnYearVo;
import com.klp.ems.domain.vo.ChainAnalysisVo;
import com.klp.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.ems.domain.bo.EmsEnergyConsumptionBo;
@@ -23,6 +28,7 @@ import com.klp.ems.domain.EmsEnergyConsumption;
import com.klp.ems.mapper.EmsEnergyConsumptionMapper;
import com.klp.ems.mapper.EmsMeterMapper;
import com.klp.ems.mapper.EmsLocationMapper;
import com.klp.ems.mapper.EmsEnergyTypeMapper;
import com.klp.ems.service.IEmsEnergyConsumptionService;
import java.time.LocalDate;
@@ -30,6 +36,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.*;
import java.math.BigDecimal;
/**
* 能耗记录Service业务层处理
@@ -44,13 +51,22 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer
private final EmsEnergyConsumptionMapper baseMapper;
private final EmsMeterMapper meterMapper;
private final EmsLocationMapper locationMapper;
private final SysUserMapper sysUserMapper;
private final EmsEnergyTypeMapper energyTypeMapper;
/**
* 查询能耗记录
*/
@Override
public EmsEnergyConsumptionVo queryById(Long energyConsumptionId){
return baseMapper.selectVoById(energyConsumptionId);
EmsEnergyConsumptionVo vo = baseMapper.selectVoById(energyConsumptionId);
if (vo != null && vo.getRecordedBy() != null) {
SysUser user = sysUserMapper.selectById(vo.getRecordedBy());
if (user != null) {
vo.setRecordedByName(user.getNickName());
}
}
return vo;
}
/**
@@ -60,6 +76,7 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer
public TableDataInfo<EmsEnergyConsumptionVo> queryPageList(EmsEnergyConsumptionBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<EmsEnergyConsumption> lqw = buildQueryWrapper(bo);
Page<EmsEnergyConsumptionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillRecordedByName(result.getRecords());
return TableDataInfo.build(result);
}
@@ -69,7 +86,41 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer
@Override
public List<EmsEnergyConsumptionVo> queryList(EmsEnergyConsumptionBo bo) {
LambdaQueryWrapper<EmsEnergyConsumption> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
List<EmsEnergyConsumptionVo> list = baseMapper.selectVoList(lqw);
fillRecordedByName(list);
return list;
}
/**
* 填充记录人名称、设备编号、能源类型名称
*/
private void fillRecordedByName(List<EmsEnergyConsumptionVo> list) {
if (list == null || list.isEmpty()) {
return;
}
for (EmsEnergyConsumptionVo vo : list) {
// 填充记录人名称
if (vo.getRecordedBy() != null) {
SysUser user = sysUserMapper.selectById(vo.getRecordedBy());
if (user != null) {
vo.setRecordedByName(user.getNickName());
}
}
// 填充设备编号和能源类型名称
if (vo.getMeterId() != null) {
EmsMeter meter = meterMapper.selectById(vo.getMeterId());
if (meter != null) {
vo.setMeterCode(meter.getMeterCode());
// 通过energyTypeId查询能源类型名称
if (meter.getEnergyTypeId() != null) {
EmsEnergyType energyType = energyTypeMapper.selectById(meter.getEnergyTypeId());
if (energyType != null) {
vo.setEnergyTypeName(energyType.getName());
}
}
}
}
}
}
private LambdaQueryWrapper<EmsEnergyConsumption> buildQueryWrapper(EmsEnergyConsumptionBo bo) {
@@ -92,6 +143,7 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer
public Boolean insertByBo(EmsEnergyConsumptionBo bo) {
EmsEnergyConsumption add = BeanUtil.toBean(bo, EmsEnergyConsumption.class);
validEntityBeforeSave(add);
add.setRecordedBy(LoginHelper.getUserId());
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setEnergyConsumptionId(add.getEnergyConsumptionId());
@@ -455,4 +507,55 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer
filter.setMeterId(null);
return meterMapper.selectMeterIds(filter);
}
/**
* 获取设备的上次抄表记录(用于自动填充起始数据)
*/
@Override
public EmsEnergyConsumptionVo getLastReadingForMeter(Long meterId) {
List<EmsEnergyConsumption> readings = baseMapper.selectLatestTwoReadings(meterId);
if (readings != null && !readings.isEmpty()) {
// 返回最新的一条记录
EmsEnergyConsumption latest = readings.get(0);
return BeanUtil.toBean(latest, EmsEnergyConsumptionVo.class);
}
return null;
}
/**
* 获取设备本月的累计消耗量
*/
@Override
public Double getMonthlyConsumption(Long meterId) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime startOfThisMonth = now.withDayOfMonth(1).toLocalDate().atStartOfDay();
LocalDateTime endOfThisMonth = now.withDayOfMonth(now.toLocalDate().lengthOfMonth())
.withHour(23).withMinute(59).withSecond(59);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
TimeRangeWithMetersBo range = new TimeRangeWithMetersBo();
range.setMeterIds(Collections.singletonList(meterId));
range.setStart(fmt.format(startOfThisMonth));
range.setEnd(fmt.format(endOfThisMonth));
Double consumption = baseMapper.sumConsumptionBetweenWithMeters(range);
return consumption != null ? consumption : 0D;
}
/**
* 获取能耗统计信息使用SQL聚合函数
*/
@Override
public Map<String, Object> getStatistics(EmsEnergyConsumptionBo bo) {
Map<String, Object> stats = baseMapper.getStatistics(bo);
if (stats == null) {
stats = new HashMap<>();
stats.put("totalCount", 0);
stats.put("totalConsumption", 0.0);
stats.put("avgConsumption", 0.0);
stats.put("maxConsumption", 0.0);
stats.put("minConsumption", 0.0);
}
return stats;
}
}

View File

@@ -6,20 +6,33 @@ import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.ems.domain.bo.*;
import com.klp.ems.domain.vo.EmsRateTierPeriodLinkVo;
import com.klp.ems.mapper.EmsRateTierPeriodLinkMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.ems.domain.bo.EmsEnergyRateBo;
import com.klp.ems.domain.vo.EmsEnergyRateVo;
import com.klp.ems.domain.vo.EmsRateTierVo;
import com.klp.ems.domain.vo.EmsRateTimePeriodLinkVo;
import com.klp.ems.domain.EmsEnergyRate;
import com.klp.ems.domain.EmsRateTier;
import com.klp.ems.domain.EmsRateTimePeriodLink;
import com.klp.ems.mapper.EmsEnergyRateMapper;
import com.klp.ems.mapper.EmsRateTierMapper;
import com.klp.ems.mapper.EmsRateTimePeriodLinkMapper;
import com.klp.ems.service.IEmsEnergyRateService;
import com.klp.ems.service.IEmsRateTierService;
import com.klp.ems.service.IEmsRateTimePeriodLinkService;
import com.klp.ems.service.IEmsRateTierPeriodLinkService;
import com.klp.ems.service.IEmsTimePeriodService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 能源费率currency 为 INT0=CNY,1=USD,2=EURService业务层处理
* 能源费率Service业务层处理
* 支持:固定费率、峰谷分时、阶梯电价、峰谷+阶梯组合
*
* @author Joshi
* @date 2025-09-28
@@ -29,6 +42,11 @@ import java.util.Collection;
public class EmsEnergyRateServiceImpl implements IEmsEnergyRateService {
private final EmsEnergyRateMapper baseMapper;
private final IEmsRateTierService rateTierService;
private final IEmsRateTimePeriodLinkService rateTimePeriodLinkService;
private final EmsRateTierMapper rateTierMapper;
private final IEmsRateTierPeriodLinkService rateTierPeriodLinkService;
private final IEmsTimePeriodService iEmsTimePeriodService;
/**
* 查询能源费率currency 为 INT0=CNY,1=USD,2=EUR
@@ -45,6 +63,10 @@ public class EmsEnergyRateServiceImpl implements IEmsEnergyRateService {
public TableDataInfo<EmsEnergyRateVo> queryPageList(EmsEnergyRateBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<EmsEnergyRate> lqw = buildQueryWrapper(bo);
Page<EmsEnergyRateVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
// 为每个费率添加梯度信息
result.getRecords().forEach(rate -> {
rate.setTiers(getRateTiers(rate.getEnergyRateId()));
});
return TableDataInfo.build(result);
}
@@ -54,7 +76,12 @@ public class EmsEnergyRateServiceImpl implements IEmsEnergyRateService {
@Override
public List<EmsEnergyRateVo> queryList(EmsEnergyRateBo bo) {
LambdaQueryWrapper<EmsEnergyRate> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
List<EmsEnergyRateVo> list = baseMapper.selectVoList(lqw);
// 为每个费率添加梯度信息
list.forEach(rate -> {
rate.setTiers(getRateTiers(rate.getEnergyRateId()));
});
return list;
}
private LambdaQueryWrapper<EmsEnergyRate> buildQueryWrapper(EmsEnergyRateBo bo) {
@@ -100,13 +127,225 @@ public class EmsEnergyRateServiceImpl implements IEmsEnergyRateService {
}
/**
* 批量删除能源费率(currency 为 INT0=CNY,1=USD,2=EUR
* 批量删除能源费率(级联删除梯度和时段费率
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
// 级联删除梯度费率和时段费率
for (Long rateId : ids) {
rateTierService.deleteByRateId(rateId);
rateTimePeriodLinkService.deleteByRateId(rateId);
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 获取费率的梯度费率列表
* 逻辑:
* - 单梯度模式:返回梯度的 rate 字段
* - 单峰谷模式:不返回梯度(梯度为空)
* - 双模式(梯度+峰谷):返回梯度在第一个时段(峰)的费率
*/
@Override
public List<EmsRateTierVo> getRateTiers(Long energyRateId) {
// 先查询费率配置
EmsEnergyRateVo energyRate = queryById(energyRateId);
if (energyRate == null) {
return new java.util.ArrayList<>();
}
List<EmsRateTierVo> tiers = rateTierService.queryByRateId(energyRateId);
// 双模式(梯度+峰谷):需要从关联表中获取费率
if (energyRate.getUseTieredPricing() == 1 && energyRate.getUsePeakValley() == 1) {
// 获取所有梯度-时段关联
List<EmsRateTierPeriodLinkVo> tierPeriodLinks = rateTierPeriodLinkService.getVoByEnergyRateId(energyRateId);
// 为每个梯度设置第一个时段(峰)的费率,并添加所有时段的费率映射
tiers.forEach(tier -> {
// 为该梯度创建时段费率映射
java.util.Map<Long, java.math.BigDecimal> tierPeriodRates = new java.util.HashMap<>();
// 找到该梯度的所有时段费率
tierPeriodLinks.stream()
.filter(link -> link.getTierId().equals(tier.getTierId()))
.forEach(link -> {
tierPeriodRates.put(link.getPeriodId(), link.getRate());
});
// 设置梯度的时段费率映射
tier.setTierPeriodRates(tierPeriodRates);
// 设置梯度的主费率为峰时段的费率
EmsRateTierPeriodLinkVo peakRate = tierPeriodLinks.stream()
.filter(link -> link.getTierId().equals(tier.getTierId()) && link.getPeriodType() == 0)
.findFirst()
.orElse(null);
if (peakRate != null) {
tier.setRate(peakRate.getRate());
}
});
}
System.out.println("getRateTiers返回梯度数量: " + tiers.size() + ", 模式: tiered=" + energyRate.getUseTieredPricing() + ", peakValley=" + energyRate.getUsePeakValley());
tiers.forEach(tier -> System.out.println(" - tierLevel=" + tier.getTierLevel() + ", rate=" + tier.getRate()));
return tiers;
}
/**
* 获取费率的时段费率列表
*/
@Override
public List<EmsRateTimePeriodLinkVo> getRateTimePeriods(Long energyRateId) {
return rateTimePeriodLinkService.queryByRateId(energyRateId);
}
/**
* 保存梯度费率返回保存后的梯度列表包含tierId
*/
@Override
public List<EmsRateTierVo> saveTiers(Long energyRateId, List<EmsRateTierBo> tiers) {
if (tiers == null || tiers.isEmpty()) {
return new java.util.ArrayList<>();
}
try {
// 先物理删除梯度-时段关联(避免外键约束失败)
com.klp.ems.mapper.EmsRateTierPeriodLinkMapper tierPeriodLinkMapper =
(com.klp.ems.mapper.EmsRateTierPeriodLinkMapper) rateTierPeriodLinkService.getBaseMapper();
int deleteLinkCount = tierPeriodLinkMapper.deleteByEnergyRateIdPhysical(energyRateId);
System.out.println("物理删除梯度-时段关联数量: " + deleteLinkCount + ", energyRateId: " + energyRateId);
// 再物理删除旧的梯度费率(使用原生 SQL
int deleteCount = rateTierMapper.deleteByRateIdPhysical(energyRateId);
System.out.println("物理删除梯度数量: " + deleteCount + ", energyRateId: " + energyRateId);
// 再保存新的梯度费率
for (EmsRateTierBo tier : tiers) {
tier.setEnergyRateId(energyRateId);
// 清除 tierId让数据库自动生成
tier.setTierId(null);
System.out.println("插入梯度: tierLevel=" + tier.getTierLevel() +
", minUsage=" + tier.getMinUsage() +
", maxUsage=" + tier.getMaxUsage() +
", rate=" + tier.getRate() +
", energyRateId=" + energyRateId);
rateTierService.insertByBo(tier);
}
// 返回保存后的梯度列表
List<EmsRateTierVo> result = rateTierService.queryByRateId(energyRateId);
System.out.println("保存梯度成功,返回数量: " + result.size());
return result;
} catch (Exception e) {
// 如果插入失败,记录错误并重新抛出
System.err.println("保存梯度失败: " + e.getMessage());
e.printStackTrace();
throw e;
}
}
/**
* 保存时段费率
*/
@Override
public Boolean saveTimePeriods(Long energyRateId, List<EmsRateTimePeriodLinkBo> timePeriods) {
if (timePeriods == null || timePeriods.isEmpty()) {
return true;
}
// 获取现有的时段费率
List<EmsRateTimePeriodLinkVo> existingLinks = rateTimePeriodLinkService.queryByRateId(energyRateId);
// 处理时段费率:新增、更新或删除
for (EmsRateTimePeriodLinkBo period : timePeriods) {
// 如果 periodId 为 null说明是新增时段需要先保存时段定义
if (period.getPeriodId() == null) {
// 创建新的时段定义
EmsTimePeriodBo timePeriodBo = new EmsTimePeriodBo();
timePeriodBo.setPeriodType(period.getPeriodType());
timePeriodBo.setPeriodName(period.getPeriodName());
timePeriodBo.setStartTime(period.getStartTime());
timePeriodBo.setEndTime(period.getEndTime());
timePeriodBo.setCrossDay(period.getCrossDay());
// 保存时段定义并获得 periodId
iEmsTimePeriodService.insertByBo(timePeriodBo);
period.setPeriodId(timePeriodBo.getPeriodId());
}
// 如果 rate 为 null说明是组合模式只保存时段定义不保存时段费率关联
if (period.getRate() == null) {
System.out.println("跳过时段费率关联保存(组合模式): periodId=" + period.getPeriodId());
continue;
}
period.setEnergyRateId(energyRateId);
// 检查是否已存在(通过 linkId
if (period.getLinkId() != null) {
// 已存在,执行更新
rateTimePeriodLinkService.updateByBo(period);
} else {
// linkId 为 null检查是否存在相同的 periodId
EmsRateTimePeriodLinkVo existingLink = existingLinks.stream()
.filter(link -> link.getPeriodId().equals(period.getPeriodId()) &&
link.getEnergyRateId().equals(energyRateId))
.findFirst()
.orElse(null);
if (existingLink != null) {
// 找到已有关联,执行更新
period.setLinkId(existingLink.getLinkId());
rateTimePeriodLinkService.updateByBo(period);
} else {
// 不存在,执行插入
rateTimePeriodLinkService.insertByBo(period);
}
}
}
// 删除不在新列表中的旧时段费率
for (EmsRateTimePeriodLinkVo existingLink : existingLinks) {
boolean stillExists = timePeriods.stream()
.anyMatch(period -> period.getPeriodId().equals(existingLink.getPeriodId()));
if (!stillExists) {
rateTimePeriodLinkService.deleteWithValidByIds(
java.util.Collections.singletonList(existingLink.getLinkId()), false);
}
}
return true;
}
/**
* 获取梯度的峰谷时段费率(用于梯度+峰谷组合模式)
*/
@Override
public List<EmsRateTierPeriodLinkBo> getTierPeriodLinks(Long tierId) {
return rateTierPeriodLinkService.getByTierId(tierId).stream()
.map(link -> {
EmsRateTierPeriodLinkBo bo = new EmsRateTierPeriodLinkBo();
bo.setLinkId(link.getLinkId());
bo.setTierId(link.getTierId());
bo.setPeriodId(link.getPeriodId());
bo.setRate(link.getRate());
return bo;
})
.collect(java.util.stream.Collectors.toList());
}
/**
* 保存梯度-时段关联费率(用于梯度+峰谷组合模式)
*/
@Override
public Boolean saveTierPeriodLinks(Long tierId, List<EmsRateTierPeriodLinkBo> tierPeriodLinks) {
if (tierPeriodLinks == null || tierPeriodLinks.isEmpty()) {
return true;
}
return rateTierPeriodLinkService.saveTierPeriodLinks(tierId, tierPeriodLinks);
}
}

View File

@@ -7,14 +7,21 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.poi.ExcelUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.klp.ems.domain.bo.EmsMeterBo;
import com.klp.ems.domain.vo.EmsMeterVo;
import com.klp.ems.domain.EmsMeter;
import com.klp.ems.domain.EmsEnergyType;
import com.klp.ems.domain.dto.MeterTemplateDto;
import com.klp.ems.mapper.EmsMeterMapper;
import com.klp.ems.mapper.EmsEnergyTypeMapper;
import com.klp.ems.service.IEmsMeterService;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
@@ -30,6 +37,7 @@ import java.util.Collection;
public class EmsMeterServiceImpl implements IEmsMeterService {
private final EmsMeterMapper baseMapper;
private final EmsEnergyTypeMapper energyTypeMapper;
/**
* 查询计量设备(阈值移至此处)
@@ -114,4 +122,113 @@ public class EmsMeterServiceImpl implements IEmsMeterService {
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 下载设备导入模板
*/
@Override
public void downloadTemplate(HttpServletResponse response) {
// 创建示例数据
List<MeterTemplateDto> templateData = new java.util.ArrayList<>();
// 示例1水表
MeterTemplateDto meter1 = new MeterTemplateDto();
meter1.setMeterCode("W-001");
meter1.setEnergyType("");
meter1.setModel("DL-100");
meter1.setManufacturer("厂商A");
meter1.setInstallDate(new Date());
templateData.add(meter1);
// 示例2电表
MeterTemplateDto meter2 = new MeterTemplateDto();
meter2.setMeterCode("E-001");
meter2.setEnergyType("");
meter2.setModel("DL-200");
meter2.setManufacturer("厂商B");
meter2.setInstallDate(new Date());
templateData.add(meter2);
// 示例3气表
MeterTemplateDto meter3 = new MeterTemplateDto();
meter3.setMeterCode("G-001");
meter3.setEnergyType("天然气");
meter3.setModel("DL-300");
meter3.setManufacturer("厂商C");
meter3.setInstallDate(new Date());
templateData.add(meter3);
// 导出为 Excel
ExcelUtil.exportExcel(templateData, "设备导入模板", MeterTemplateDto.class, response);
}
/**
* 导入设备
*/
@Override
public Boolean importMeters(MultipartFile file) {
try {
// 读取 Excel 文件为模板 DTO
List<MeterTemplateDto> templateList = ExcelUtil.importExcel(file.getInputStream(), MeterTemplateDto.class);
if (templateList == null || templateList.isEmpty()) {
return false;
}
// 转换为 EmsMeter 并设置默认值
List<EmsMeter> meterList = new java.util.ArrayList<>();
for (MeterTemplateDto template : templateList) {
EmsMeter meter = new EmsMeter();
meter.setMeterCode(template.getMeterCode());
meter.setModel(template.getModel());
meter.setManufacturer(template.getManufacturer());
// 安装日期为空时默认为当日
if (template.getInstallDate() != null) {
meter.setInstallDate(template.getInstallDate());
} else {
meter.setInstallDate(new Date());
}
// 设备状态默认为启用0
meter.setStatus(0L);
// 根据能源类型名称获取能源类型 ID
Long energyTypeId = getEnergyTypeIdByName(template.getEnergyType());
meter.setEnergyTypeId(energyTypeId);
meterList.add(meter);
}
// 批量插入
for (EmsMeter meter : meterList) {
validEntityBeforeSave(meter);
baseMapper.insert(meter);
}
return true;
} catch (Exception e) {
throw new RuntimeException("导入设备失败: " + e.getMessage(), e);
}
}
/**
* 根据能源类型名称获取能源类型 ID
*/
private Long getEnergyTypeIdByName(String energyTypeName) {
if (energyTypeName == null) {
return null;
}
// 从数据库查询能源类型
LambdaQueryWrapper<EmsEnergyType> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(EmsEnergyType::getName, energyTypeName.trim());
EmsEnergyType energyType = energyTypeMapper.selectOne(queryWrapper);
if (energyType != null) {
return energyType.getEnergyTypeId();
}
return null;
}
}

View File

@@ -0,0 +1,79 @@
package com.klp.ems.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.klp.ems.domain.EmsRateTierPeriodLink;
import com.klp.ems.domain.bo.EmsRateTierPeriodLinkBo;
import com.klp.ems.domain.vo.EmsRateTierPeriodLinkVo;
import com.klp.ems.mapper.EmsRateTierPeriodLinkMapper;
import com.klp.ems.service.IEmsRateTierPeriodLinkService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
/**
* 梯度与时段关联 Service 实现
*
* @author Joshi
* @date 2025-12-05
*/
@Service
@RequiredArgsConstructor
public class EmsRateTierPeriodLinkServiceImpl extends ServiceImpl<EmsRateTierPeriodLinkMapper, EmsRateTierPeriodLink>
implements IEmsRateTierPeriodLinkService {
private final EmsRateTierPeriodLinkMapper emsRateTierPeriodLinkMapper;
@Override
public List<EmsRateTierPeriodLink> getByTierId(Long tierId) {
return emsRateTierPeriodLinkMapper.selectByTierId(tierId);
}
@Override
@Transactional
public Boolean deleteByTierId(Long tierId) {
return emsRateTierPeriodLinkMapper.deleteByTierId(tierId) > 0;
}
@Override
@Transactional
public Boolean deleteByEnergyRateId(Long energyRateId) {
return emsRateTierPeriodLinkMapper.deleteByEnergyRateId(energyRateId) > 0;
}
@Override
public List<EmsRateTierPeriodLinkVo> getVoByEnergyRateId(Long energyRateId) {
return emsRateTierPeriodLinkMapper.selectVoByEnergyRateId(energyRateId);
}
@Override
@Transactional
public Boolean saveTierPeriodLinks(Long tierId, List<EmsRateTierPeriodLinkBo> tierPeriodLinks) {
System.out.println("保存梯度-时段关联: tierId=" + tierId + ", 关联数量=" + tierPeriodLinks.size());
tierPeriodLinks.forEach(bo -> {
System.out.println(" - periodId=" + bo.getPeriodId() + ", rate=" + bo.getRate());
});
// 先物理删除该梯度的所有关联(避免死锁)
int deleteCount = emsRateTierPeriodLinkMapper.deleteByTierIdPhysical(tierId);
System.out.println("物理删除梯度-时段关联数量: " + deleteCount + ", tierId: " + tierId);
// 再批量插入新的关联
List<EmsRateTierPeriodLink> links = tierPeriodLinks.stream()
.map(bo -> {
EmsRateTierPeriodLink link = new EmsRateTierPeriodLink();
link.setTierId(tierId);
link.setPeriodId(bo.getPeriodId());
link.setRate(bo.getRate());
link.setRemark(bo.getRemark());
return link;
})
.collect(Collectors.toList());
boolean result = this.saveBatch(links);
System.out.println("梯度-时段关联保存结果: " + result);
return result;
}
}

View File

@@ -0,0 +1,98 @@
package com.klp.ems.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.ems.domain.bo.EmsRateTierBo;
import com.klp.ems.domain.vo.EmsRateTierVo;
import com.klp.ems.domain.EmsRateTier;
import com.klp.ems.mapper.EmsRateTierMapper;
import com.klp.ems.service.IEmsRateTierService;
import java.util.Collection;
import java.util.List;
/**
* 梯度费率Service业务层处理
*
* @author Joshi
* @date 2025-12-05
*/
@RequiredArgsConstructor
@Service
public class EmsRateTierServiceImpl implements IEmsRateTierService {
private final EmsRateTierMapper baseMapper;
@Override
public EmsRateTierVo queryById(Long tierId) {
return baseMapper.selectVoById(tierId);
}
@Override
public TableDataInfo<EmsRateTierVo> queryPageList(EmsRateTierBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<EmsRateTier> lqw = buildQueryWrapper(bo);
Page<EmsRateTierVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<EmsRateTierVo> queryList(EmsRateTierBo bo) {
LambdaQueryWrapper<EmsRateTier> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
public List<EmsRateTierVo> queryByRateId(Long energyRateId) {
return baseMapper.selectByRateId(energyRateId);
}
private LambdaQueryWrapper<EmsRateTier> buildQueryWrapper(EmsRateTierBo bo) {
LambdaQueryWrapper<EmsRateTier> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getEnergyRateId() != null, EmsRateTier::getEnergyRateId, bo.getEnergyRateId());
lqw.eq(bo.getTierLevel() != null, EmsRateTier::getTierLevel, bo.getTierLevel());
return lqw;
}
@Override
public Boolean insertByBo(EmsRateTierBo bo) {
EmsRateTier add = BeanUtil.toBean(bo, EmsRateTier.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setTierId(add.getTierId());
}
return flag;
}
@Override
public Boolean updateByBo(EmsRateTierBo bo) {
EmsRateTier update = BeanUtil.toBean(bo, EmsRateTier.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(EmsRateTier entity) {
// TODO 做一些数据校验
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public Boolean deleteByRateId(Long energyRateId) {
LambdaQueryWrapper<EmsRateTier> lqw = Wrappers.lambdaQuery();
lqw.eq(EmsRateTier::getEnergyRateId, energyRateId);
return baseMapper.delete(lqw) > 0;
}
}

View File

@@ -0,0 +1,98 @@
package com.klp.ems.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.ems.domain.bo.EmsRateTimePeriodLinkBo;
import com.klp.ems.domain.vo.EmsRateTimePeriodLinkVo;
import com.klp.ems.domain.EmsRateTimePeriodLink;
import com.klp.ems.mapper.EmsRateTimePeriodLinkMapper;
import com.klp.ems.service.IEmsRateTimePeriodLinkService;
import java.util.Collection;
import java.util.List;
/**
* 费率与时间段关联Service业务层处理
*
* @author Joshi
* @date 2025-12-05
*/
@RequiredArgsConstructor
@Service
public class EmsRateTimePeriodLinkServiceImpl implements IEmsRateTimePeriodLinkService {
private final EmsRateTimePeriodLinkMapper baseMapper;
@Override
public EmsRateTimePeriodLinkVo queryById(Long linkId) {
return baseMapper.selectVoById(linkId);
}
@Override
public TableDataInfo<EmsRateTimePeriodLinkVo> queryPageList(EmsRateTimePeriodLinkBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<EmsRateTimePeriodLink> lqw = buildQueryWrapper(bo);
Page<EmsRateTimePeriodLinkVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<EmsRateTimePeriodLinkVo> queryList(EmsRateTimePeriodLinkBo bo) {
LambdaQueryWrapper<EmsRateTimePeriodLink> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
@Override
public List<EmsRateTimePeriodLinkVo> queryByRateId(Long energyRateId) {
return baseMapper.selectByRateId(energyRateId);
}
private LambdaQueryWrapper<EmsRateTimePeriodLink> buildQueryWrapper(EmsRateTimePeriodLinkBo bo) {
LambdaQueryWrapper<EmsRateTimePeriodLink> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getEnergyRateId() != null, EmsRateTimePeriodLink::getEnergyRateId, bo.getEnergyRateId());
lqw.eq(bo.getPeriodId() != null, EmsRateTimePeriodLink::getPeriodId, bo.getPeriodId());
return lqw;
}
@Override
public Boolean insertByBo(EmsRateTimePeriodLinkBo bo) {
EmsRateTimePeriodLink add = BeanUtil.toBean(bo, EmsRateTimePeriodLink.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setLinkId(add.getLinkId());
}
return flag;
}
@Override
public Boolean updateByBo(EmsRateTimePeriodLinkBo bo) {
EmsRateTimePeriodLink update = BeanUtil.toBean(bo, EmsRateTimePeriodLink.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(EmsRateTimePeriodLink entity) {
// TODO 做一些数据校验
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public Boolean deleteByRateId(Long energyRateId) {
LambdaQueryWrapper<EmsRateTimePeriodLink> lqw = Wrappers.lambdaQuery();
lqw.eq(EmsRateTimePeriodLink::getEnergyRateId, energyRateId);
return baseMapper.delete(lqw) > 0;
}
}

View File

@@ -0,0 +1,88 @@
package com.klp.ems.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.ems.domain.bo.EmsTimePeriodBo;
import com.klp.ems.domain.vo.EmsTimePeriodVo;
import com.klp.ems.domain.EmsTimePeriod;
import com.klp.ems.mapper.EmsTimePeriodMapper;
import com.klp.ems.service.IEmsTimePeriodService;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 时间段Service业务层处理
*
* @author Joshi
* @date 2025-12-05
*/
@RequiredArgsConstructor
@Service
public class EmsTimePeriodServiceImpl implements IEmsTimePeriodService {
private final EmsTimePeriodMapper baseMapper;
@Override
public EmsTimePeriodVo queryById(Long periodId) {
return baseMapper.selectVoById(periodId);
}
@Override
public TableDataInfo<EmsTimePeriodVo> queryPageList(EmsTimePeriodBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<EmsTimePeriod> lqw = buildQueryWrapper(bo);
Page<EmsTimePeriodVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<EmsTimePeriodVo> queryList(EmsTimePeriodBo bo) {
LambdaQueryWrapper<EmsTimePeriod> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<EmsTimePeriod> buildQueryWrapper(EmsTimePeriodBo bo) {
LambdaQueryWrapper<EmsTimePeriod> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getPeriodId() != null, EmsTimePeriod::getPeriodId, bo.getPeriodId());
lqw.like(bo.getPeriodName() != null, EmsTimePeriod::getPeriodName, bo.getPeriodName());
lqw.eq(bo.getPeriodType() != null, EmsTimePeriod::getPeriodType, bo.getPeriodType());
return lqw;
}
@Override
public Boolean insertByBo(EmsTimePeriodBo bo) {
EmsTimePeriod add = BeanUtil.toBean(bo, EmsTimePeriod.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPeriodId(add.getPeriodId());
}
return flag;
}
@Override
public Boolean updateByBo(EmsTimePeriodBo bo) {
EmsTimePeriod update = BeanUtil.toBean(bo, EmsTimePeriod.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(EmsTimePeriod entity) {
// TODO 做一些数据校验
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,55 @@
package com.klp.ems.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.ems.domain.bo.EnergyCostReportBo;
import com.klp.ems.domain.vo.EnergyCostSummaryVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.mapper.WmsEnergyCoilDailyMapper;
import com.klp.ems.service.IEnergyCostReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* 能源成本报表 Service 实现
*/
@Service
@RequiredArgsConstructor
public class EnergyCostReportServiceImpl implements IEnergyCostReportService {
private final WmsEnergyCoilDailyMapper coilDailyMapper;
@Override
public Map<String, Object> overview(EnergyCostReportBo bo) {
return coilDailyMapper.selectEnergyOverview(bo);
}
@Override
public List<EnergyCostSummaryVo> summary(EnergyCostReportBo bo) {
String group = bo.getGroupBy();
Function<EnergyCostReportBo, List<EnergyCostSummaryVo>> function;
if ("warehouse".equalsIgnoreCase(group)) {
function = coilDailyMapper::summaryByWarehouse;
} else if ("meter".equalsIgnoreCase(group)) {
function = coilDailyMapper::summaryByMeter;
} else if ("task".equalsIgnoreCase(group)) {
function = coilDailyMapper::summaryByTask;
} else {
function = coilDailyMapper::summaryByEnergyType;
}
List<EnergyCostSummaryVo> list = function.apply(bo);
return list == null ? Collections.emptyList() : list;
}
@Override
public TableDataInfo<WmsEnergyCoilDailyVo> detail(EnergyCostReportBo bo, PageQuery pageQuery) {
Page<WmsEnergyCoilDailyVo> page = coilDailyMapper.selectReportDetail(pageQuery.build(), bo);
return TableDataInfo.build(page);
}
}

View File

@@ -0,0 +1,126 @@
package com.klp.ems.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.ems.domain.*;
import com.klp.ems.domain.bo.WmsEnergyCoilDailyBo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyStatisticsVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.mapper.*;
import com.klp.ems.service.IWmsEnergyCoilDailyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 钢卷日能源成本分摊结果 Service 实现
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class WmsEnergyCoilDailyServiceImpl implements IWmsEnergyCoilDailyService {
private final WmsEnergyCoilDailyMapper baseMapper;
@Override
public WmsEnergyCoilDailyVo queryById(Long energyCostId) {
return baseMapper.selectVoById(energyCostId);
}
@Override
public TableDataInfo<WmsEnergyCoilDailyVo> queryPageList(WmsEnergyCoilDailyBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsEnergyCoilDaily> lqw = buildQueryWrapper(bo);
Page<WmsEnergyCoilDailyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<WmsEnergyCoilDailyVo> queryList(WmsEnergyCoilDailyBo bo) {
return baseMapper.selectVoList(buildQueryWrapper(bo));
}
@Override
public TableDataInfo<WmsEnergyCoilDailyVo> queryPendingActionCoilCost(WmsEnergyCoilDailyBo bo, PageQuery pageQuery) {
// 使用SQL一次性查询待操作钢卷的能源成本
// 所有的关联、聚合、计算都在SQL中完成性能更高
List<WmsEnergyCoilDailyVo> resultList = baseMapper.selectPendingActionCoilCost();
if (CollUtil.isEmpty(resultList)) {
log.warn("[PendingActionCoilCost] No pending action coils found");
return TableDataInfo.build(new Page<>());
}
// 分页处理
int pageNum = pageQuery.getPageNum();
int pageSize = pageQuery.getPageSize();
int start = (pageNum - 1) * pageSize;
int end = Math.min(start + pageSize, resultList.size());
List<WmsEnergyCoilDailyVo> pageData = resultList.subList(start, end);
Page<WmsEnergyCoilDailyVo> resultPage = new Page<>(pageNum, pageSize);
resultPage.setRecords(pageData);
resultPage.setTotal(resultList.size());
return TableDataInfo.build(resultPage);
}
@Override
public WmsEnergyCoilDailyStatisticsVo queryPendingActionCoilCostStatistics(String enterCoilNo, String currentCoilNo, Long warehouseId) {
return baseMapper.selectPendingActionCoilCostStatistics(enterCoilNo, currentCoilNo, warehouseId);
}
@Override
public Boolean insertByBo(WmsEnergyCoilDailyBo bo) {
WmsEnergyCoilDaily add = BeanUtil.toBean(bo, WmsEnergyCoilDaily.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setEnergyCostId(add.getEnergyCostId());
}
return flag;
}
@Override
public Boolean updateByBo(WmsEnergyCoilDailyBo bo) {
WmsEnergyCoilDaily update = BeanUtil.toBean(bo, WmsEnergyCoilDaily.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 判断是否允许删除(例如已用于成本对账)
}
return baseMapper.deleteBatchIds(ids) > 0;
}
private LambdaQueryWrapper<WmsEnergyCoilDaily> buildQueryWrapper(WmsEnergyCoilDailyBo bo) {
LambdaQueryWrapper<WmsEnergyCoilDaily> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getTaskId() != null, WmsEnergyCoilDaily::getTaskId, bo.getTaskId());
lqw.eq(bo.getCalcDate() != null, WmsEnergyCoilDaily::getCalcDate, bo.getCalcDate());
lqw.eq(bo.getCoilId() != null, WmsEnergyCoilDaily::getCoilId, bo.getCoilId());
lqw.eq(bo.getWarehouseId() != null, WmsEnergyCoilDaily::getWarehouseId, bo.getWarehouseId());
lqw.eq(bo.getActualWarehouseId() != null, WmsEnergyCoilDaily::getActualWarehouseId, bo.getActualWarehouseId());
lqw.eq(bo.getEnergyTypeId() != null, WmsEnergyCoilDaily::getEnergyTypeId, bo.getEnergyTypeId());
lqw.eq(bo.getMeterId() != null, WmsEnergyCoilDaily::getMeterId, bo.getMeterId());
lqw.ge(bo.getStartDate() != null, WmsEnergyCoilDaily::getCalcDate, bo.getStartDate());
lqw.le(bo.getEndDate() != null, WmsEnergyCoilDaily::getCalcDate, bo.getEndDate());
lqw.like(StringUtils.isNotBlank(bo.getEnterCoilNo()), WmsEnergyCoilDaily::getEnterCoilNo, bo.getEnterCoilNo());
lqw.like(StringUtils.isNotBlank(bo.getCurrentCoilNo()), WmsEnergyCoilDaily::getCurrentCoilNo, bo.getCurrentCoilNo());
return lqw;
}
private void validEntityBeforeSave(WmsEnergyCoilDaily entity) {
// TODO 数据校验(如同一 taskId + coilId 不重复)
}
}