add 新增查询枪均效率分析接口

This commit is contained in:
Lemon
2026-04-07 10:33:47 +08:00
parent f7d541d44a
commit 80a0f2ec22
3 changed files with 156 additions and 14 deletions

View File

@@ -11,6 +11,7 @@ import com.jsowell.pile.dto.ParkingCouponRecordQueryDTO;
import com.jsowell.pile.dto.business.BusinessOperationAnalysisQueryDTO;
import com.jsowell.pile.service.BusinessFinancialService;
import com.jsowell.pile.vo.uniapp.business.BusinessOperationAnalysisVO;
import com.jsowell.pile.vo.uniapp.business.BusinessGunEfficiencyAnalysisVO;
import com.jsowell.pile.vo.web.MerchantOrderReportVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -101,7 +102,9 @@ public class BusinessFinancialController extends BaseController {
logger.info("查询经营分析 params:{}", JSONObject.toJSONString(dto));
RestApiResponse<?> response;
try {
validateBusinessOperationQuery(dto);
if (dto == null) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
BusinessOperationAnalysisVO result = businessFinancialService.getBusinessOperationAnalysis(dto);
response = new RestApiResponse<>(result);
logger.info("查询经营分析成功 startTime:{}, endTime:{}, selectedMetricCode:{}",
@@ -117,18 +120,30 @@ public class BusinessFinancialController extends BaseController {
}
/**
* 校验经营分析查询参数
* 查询枪均效率分析
*
* @param dto 查询参数
* @return 枪均效率分析
*/
private void validateBusinessOperationQuery(BusinessOperationAnalysisQueryDTO dto) {
if (dto == null) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
boolean startTimeBlank = StringUtils.isBlank(dto.getStartTime());
boolean endTimeBlank = StringUtils.isBlank(dto.getEndTime());
if (startTimeBlank ^ endTimeBlank) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
@PostMapping("/gunEfficiencyAnalysis")
public RestApiResponse<?> getBusinessGunEfficiencyAnalysis(@RequestBody BusinessOperationAnalysisQueryDTO dto) {
logger.info("查询枪均效率分析 params:{}", JSONObject.toJSONString(dto));
RestApiResponse<?> response;
try {
if (dto == null) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
BusinessGunEfficiencyAnalysisVO result = businessFinancialService.getBusinessGunEfficiencyAnalysis(dto);
response = new RestApiResponse<>(result);
logger.info("查询枪均效率分析成功 startTime:{}, endTime:{}",
dto.getStartTime(), dto.getEndTime());
} catch (BusinessException e) {
logger.warn("查询枪均效率分析业务异常 code:{}, message:{}", e.getCode(), e.getMessage(), e);
response = new RestApiResponse<>(e.getCode(), e.getMessage());
} catch (Exception e) {
logger.error("查询枪均效率分析系统异常 params:{}", JSONObject.toJSONString(dto), e);
response = new RestApiResponse<>(e);
}
return response;
}
}

View File

@@ -4,6 +4,7 @@ import com.jsowell.common.core.page.PageResponse;
import com.jsowell.pile.dto.MerchantOrderReportDTO;
import com.jsowell.pile.dto.ParkingCouponRecordQueryDTO;
import com.jsowell.pile.dto.business.BusinessOperationAnalysisQueryDTO;
import com.jsowell.pile.vo.uniapp.business.BusinessGunEfficiencyAnalysisVO;
import com.jsowell.pile.vo.uniapp.business.BusinessOperationAnalysisVO;
import com.jsowell.pile.vo.web.MerchantOrderReportVO;
import com.jsowell.pile.vo.web.ParkingCouponRecordVO;
@@ -26,4 +27,12 @@ public interface BusinessFinancialService {
* @return 经营分析
*/
BusinessOperationAnalysisVO getBusinessOperationAnalysis(BusinessOperationAnalysisQueryDTO dto);
/**
* 查询枪均效率分析
*
* @param dto 查询条件
* @return 枪均效率分析
*/
BusinessGunEfficiencyAnalysisVO getBusinessGunEfficiencyAnalysis(BusinessOperationAnalysisQueryDTO dto);
}

View File

@@ -15,13 +15,16 @@ import com.jsowell.pile.dto.ParkingCouponRecordQueryDTO;
import com.jsowell.pile.dto.business.BusinessOperationAnalysisQueryDTO;
import com.jsowell.pile.dto.business.BusinessOperationDateRangeDTO;
import com.jsowell.pile.dto.business.BusinessOperationSummaryDTO;
import com.jsowell.pile.domain.PileConnectorInfo;
import com.jsowell.pile.domain.SettleOrderReport;
import com.jsowell.pile.service.BusinessFinancialService;
import com.jsowell.pile.service.CarCouponRecordService;
import com.jsowell.pile.service.ClearingWithdrawInfoService;
import com.jsowell.pile.service.PileConnectorInfoService;
import com.jsowell.pile.service.PileStationInfoService;
import com.jsowell.pile.service.SettleOrderReportService;
import com.jsowell.pile.util.UserUtils;
import com.jsowell.pile.vo.uniapp.business.BusinessGunEfficiencyAnalysisVO;
import com.jsowell.pile.vo.uniapp.business.BusinessOperationAnalysisVO;
import com.jsowell.pile.vo.uniapp.business.BusinessOperationDiagnosisItemVO;
import com.jsowell.pile.vo.uniapp.business.BusinessOperationMetricVO;
@@ -34,10 +37,12 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 运营端小程序财务相关Service
@@ -69,6 +74,9 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
@Autowired
private PileStationInfoService pileStationInfoService;
@Autowired
private PileConnectorInfoService pileConnectorInfoService;
/**
* 我的钱包查询
* @param dto
@@ -217,6 +225,53 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
.build();
}
/**
* 查询枪均效率分析
*
* @param dto 查询条件
* @return 枪均效率分析
*/
@Override
public BusinessGunEfficiencyAnalysisVO getBusinessGunEfficiencyAnalysis(BusinessOperationAnalysisQueryDTO dto) {
if (dto == null) {
return null;
}
if (StringUtils.isBlank(dto.getStartTime()) && StringUtils.isBlank(dto.getEndTime())) {
LocalDate endDate = LocalDate.now();
LocalDate startDate = endDate.minusDays(6);
dto.setStartTime(startDate.toString());
dto.setEndTime(endDate.toString());
}
BusinessOperationDateRangeDTO range = buildDateRange(dto);
List<String> stationIdList = resolveStationIds(dto.getStationIdList());
BusinessOperationSummaryDTO summary = buildOperationSummary(
stationIdList, range.getCurrentStart(), range.getCurrentEnd());
BigDecimal connectorCount = BigDecimal.valueOf(countConnectors(stationIdList));
BigDecimal dayCount = BigDecimal.valueOf(calculateInclusiveDays(range.getCurrentStart(), range.getCurrentEnd()));
BigDecimal connectorDayCount = connectorCount.multiply(dayCount);
BigDecimal gunAvgDailyServiceFee = BigDecimalUtils.safeDivide(summary.getServiceAmount(), connectorDayCount, 2);
BigDecimal gunAvgDailyElectricity = BigDecimalUtils.safeDivide(summary.getUseElectricity(), connectorDayCount, 4);
BigDecimal avgServiceFeePerDegree = BigDecimalUtils.safeDivide(summary.getServiceAmount(), summary.getUseElectricity(), 4);
BigDecimal gunAvgDailyChargeTimeMinutes = BigDecimalUtils.safeDivide(summary.getChargeTime(), connectorDayCount, 2);
BigDecimal avgPower = BigDecimalUtils.safeDivide(
summary.getUseElectricity().multiply(new BigDecimal("60")),
summary.getChargeTime(),
4);
return BusinessGunEfficiencyAnalysisVO.builder()
.startTime(range.getCurrentStart())
.endTime(range.getCurrentEnd())
.gunAvgDailyServiceFee(BigDecimalUtils.normalize(gunAvgDailyServiceFee))
.gunAvgDailyElectricity(BigDecimalUtils.normalize(gunAvgDailyElectricity))
.avgServiceFeePerDegree(BigDecimalUtils.normalize(avgServiceFeePerDegree))
.gunAvgDailyChargeTime(formatMinutesToHourMinute(gunAvgDailyChargeTimeMinutes))
.avgPower(BigDecimalUtils.normalize(avgPower))
.build();
}
/**
* 构建当前选中指标对应的最大影响因素
*
@@ -333,13 +388,29 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
* @return 实际查询站点ID列表
*/
private List<String> resolveStationIds(List<String> stationIdList) {
if (!CollectionUtils.isEmpty(stationIdList)) {
return stationIdList;
List<String> authorizedStationIds = getAuthorizedStationIds();
if (authorizedStationIds == null) {
return CollectionUtils.isEmpty(stationIdList) ? null : stationIdList;
}
if (!CollectionUtils.isEmpty(stationIdList)) {
return stationIdList.stream()
.filter(authorizedStationIds::contains)
.distinct()
.collect(Collectors.toList());
}
return authorizedStationIds;
}
/**
* 获取当前账号可访问的站点ID列表平台账号返回null表示不限制
*
* @return 站点ID列表
*/
private List<String> getAuthorizedStationIds() {
try {
AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap();
if (authorizedMap == null) {
return stationIdList;
return null;
}
if (!CollectionUtils.isEmpty(authorizedMap.getStationDeptIds())) {
return pileStationInfoService.queryByStationDeptIds(authorizedMap.getStationDeptIds());
@@ -350,7 +421,7 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
} catch (Exception e) {
log.warn("解析经营分析站点权限失败", e);
}
return stationIdList;
return null;
}
/**
@@ -364,6 +435,9 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
private BusinessOperationSummaryDTO buildOperationSummary(List<String> stationIdList,
String startTime,
String endTime) {
if (stationIdList != null && stationIdList.isEmpty()) {
return new BusinessOperationSummaryDTO();
}
List<SettleOrderReport> reportList = settleOrderReportService.queryOrderReport(
stationIdList, startTime, endTime);
if (CollectionUtils.isEmpty(reportList)) {
@@ -382,4 +456,48 @@ public class BusinessFinancialServiceImpl implements BusinessFinancialService {
summary.setAvgChargeTime(BigDecimalUtils.safeDivide(summary.getChargeTime(), summary.getOrderCount(), 2));
return summary;
}
/**
* 统计站点范围内的枪口数量
*
* @param stationIdList 站点ID列表
* @return 枪口数量
*/
private int countConnectors(List<String> stationIdList) {
if (stationIdList == null) {
return pileConnectorInfoService.selectPileConnectorInfoList(new PileConnectorInfo()).size();
}
if (stationIdList.isEmpty()) {
return 0;
}
return pileConnectorInfoService.batchSelectConnectorList(stationIdList).size();
}
/**
* 计算包含起止日期在内的天数
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 天数
*/
private long calculateInclusiveDays(String startTime, String endTime) {
LocalDate startDate = LocalDate.parse(startTime);
LocalDate endDate = LocalDate.parse(endTime);
return ChronoUnit.DAYS.between(startDate, endDate) + 1;
}
/**
* 将分钟数转换为xxhxxm格式
*
* @param minutes 分钟数
* @return 格式化结果
*/
private String formatMinutesToHourMinute(BigDecimal minutes) {
long totalMinutes = BigDecimalUtils.nullToZero(minutes)
.setScale(0, RoundingMode.HALF_UP)
.longValue();
long hours = totalMinutes / 60;
long remainMinutes = totalMinutes % 60;
return String.format("%02dh%02dm", hours, remainMinutes);
}
}