供需平衡分析
parent
75162d9e33
commit
b278261480
|
|
@ -48,7 +48,7 @@ public class RiceSupportBalanceController {
|
|||
return R.ok(true);
|
||||
}
|
||||
|
||||
@Operation(summary = "来水预测-分页查询,供需平衡板")
|
||||
@Operation(summary = "来水预测-分页查询,供需平衡版")
|
||||
@PostMapping("/icpage")
|
||||
public R<Page<IcWaterForecast>> icPage(@RequestBody RiceSupportBalanceCaculatePageSo pageSo){
|
||||
Page<IcWaterForecast> page = riceSupportBalanceService.icPage(pageSo);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.gunshi.project.hsz.entity.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
|
@ -13,8 +14,10 @@ public class RiceSupportBalanceCaculateDto {
|
|||
|
||||
private String planName;//方案名称
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime startTime;//开始时间
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime endTime;//结束时间
|
||||
|
||||
private Long icId;//来水方案Id
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
List<StZvarlB> list = stZvarlBService.lambdaQuery().orderByAsc(StZvarlB::getRz).list();
|
||||
BigDecimal w = stZvarlBService.getWByZvarl(list, stRsvrRReal.getRz());//获取库容
|
||||
BigDecimal deadW = stZvarlBService.getWByZvarl(list, deadLev);//死水位库容
|
||||
Integer year = icWaterForecast.getYear();//获取相似年
|
||||
Integer year = riceRqWater.getRiceGrowConfig().getYear();//获取相似年
|
||||
if(dto.getStartTime().isAfter(today)){
|
||||
// 总来水量 = 当前~开始时间这一段时间的来水量 + 来回方案来水
|
||||
//方案来水量的时间范围 今天1号,开始时间4号,需要计算1-3号共3天
|
||||
|
|
@ -118,13 +118,13 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
break;
|
||||
}
|
||||
}
|
||||
// 总来水量 = 当前到开始时间的降雨来水量 + 方案来水
|
||||
// 总来水量 = 当前到开始时间的降雨来水量 + 方案来水(长期预测为万m³,短期预测为m³ 所以如果为短期,则需要进行÷10000
|
||||
BigDecimal currentToStartWater = totalRainfallWater; // 这里假设totalRainfallWater就是需要的来水量
|
||||
totalIcWater = totalIcWater.add(currentToStartWater).add(icWaterForecast.getForecastWater()); // 将当前到开始时间的来水量加入总来水量
|
||||
totalIcWater = totalIcWater.add(currentToStartWater).add(icWaterForecast.getType() == 0? icWaterForecast.getForecastWater(): icWaterForecast.getForecastWater().divide(new BigDecimal("10000"))); // 将当前到开始时间的来水量加入总来水量
|
||||
|
||||
}else{
|
||||
// 总来水量 = 当前蓄水量 + 来水方案中的来水
|
||||
BigDecimal forecastWater = icWaterForecast.getForecastWater();
|
||||
BigDecimal forecastWater = icWaterForecast.getType() == 0? icWaterForecast.getForecastWater(): icWaterForecast.getForecastWater().divide(new BigDecimal("10000"));
|
||||
totalIcWater = w.add(forecastWater);
|
||||
}
|
||||
BigDecimal totalNeedWater = BigDecimal.ZERO;
|
||||
|
|
@ -181,7 +181,7 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
// 计算灌溉用水的缩放比例
|
||||
BigDecimal irrigationRatio;
|
||||
if (totalIrrigationNeed.compareTo(BigDecimal.ZERO) > 0) {
|
||||
irrigationRatio = totalWaterForIrrigation.divide(totalIrrigationNeed, 4, BigDecimal.ROUND_HALF_UP);
|
||||
irrigationRatio = totalIcWater.divide(totalNeedWater, 4, BigDecimal.ROUND_HALF_UP);
|
||||
} else {
|
||||
irrigationRatio = BigDecimal.ZERO;
|
||||
}
|
||||
|
|
@ -193,10 +193,11 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
riceSupportBalance.setEndTime(dto.getEndTime());
|
||||
riceSupportBalance.setCreateTime(LocalDateTime.now());
|
||||
riceSupportBalance.setTotalSupport(totalPlan);
|
||||
riceSupportBalance.setTotalCost(totalIrrigationNeed);
|
||||
riceSupportBalance.setTotalCost(totalNeedWater);
|
||||
riceSupportBalance.setCreateName(dto.getCreateName());
|
||||
riceSupportBalance.setStatus(0);
|
||||
this.save(riceSupportBalance);
|
||||
riceSupportBalance.setPlanName(dto.getPlanName());
|
||||
boolean save = this.save(riceSupportBalance);
|
||||
// 创建final或effectively final的局部变量副本
|
||||
final Long mainId = riceSupportBalance.getId();
|
||||
final BigDecimal finalDailyEcoWaterUse = dailyEcoWaterUse;
|
||||
|
|
@ -205,10 +206,10 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
final List<RiceSupportMidCaculate> finalRiceSupportMidCaculates = new ArrayList<>(riceSupportMidCaculates);
|
||||
|
||||
// 在新线程中执行计算和保存
|
||||
//TODO 这样做会有事务问题(如果明细数据计算失败,那么会导致 只有主表数据,没有明细数据(当然也可以保持同步计算逻辑)
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<RiceSupportBalanceDetail> saveDetails = new ArrayList<>();
|
||||
|
||||
for (LocalDateTime localDateTime : finalAllDays) {
|
||||
RiceSupportBalanceDetail entity = new RiceSupportBalanceDetail();
|
||||
entity.setTm(localDateTime);
|
||||
|
|
@ -216,11 +217,38 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
// 查找当前日期属于哪个生长周期,计算灌溉需水量
|
||||
BigDecimal dailyIrrigationNeed = BigDecimal.ZERO; // 灌溉需水量
|
||||
for (RiceSupportMidCaculate caculate : finalRiceSupportMidCaculates) {
|
||||
if (!localDateTime.isBefore(caculate.getStartTime()) &&
|
||||
!localDateTime.isAfter(caculate.getEndTime())) {
|
||||
// 提取月份和日,忽略年份
|
||||
int currentMonth = localDateTime.getMonthValue();
|
||||
int currentDay = localDateTime.getDayOfMonth();
|
||||
|
||||
int startMonth = caculate.getStartTime().getMonthValue();
|
||||
int startDay = caculate.getStartTime().getDayOfMonth();
|
||||
|
||||
int endMonth = caculate.getEndTime().getMonthValue();
|
||||
int endDay = caculate.getEndTime().getDayOfMonth();
|
||||
|
||||
// 判断日期是否在周期内(只比较月日)
|
||||
boolean isInCycle = false;
|
||||
|
||||
if (startMonth < endMonth || (startMonth == endMonth && startDay <= endDay)) {
|
||||
// 正常情况:开始月日 <= 结束月日(不跨年)
|
||||
if ((currentMonth > startMonth || (currentMonth == startMonth && currentDay >= startDay)) &&
|
||||
(currentMonth < endMonth || (currentMonth == endMonth && currentDay <= endDay))) {
|
||||
isInCycle = true;
|
||||
}
|
||||
} else {
|
||||
// 跨年情况:开始月日 > 结束月日(如11月到次年2月)
|
||||
if ((currentMonth > startMonth || (currentMonth == startMonth && currentDay >= startDay)) ||
|
||||
(currentMonth < endMonth || (currentMonth == endMonth && currentDay <= endDay))) {
|
||||
isInCycle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isInCycle) {
|
||||
// 计算该生长周期的天数
|
||||
int daysInCycle = LocalDateTimeUtils.getTotalDayByRangeDate(
|
||||
caculate.getStartTime(), caculate.getEndTime()
|
||||
int daysInCycle = LocalDateTimeUtils.calculateDaysIgnoringYear(
|
||||
caculate.getStartTime(),
|
||||
caculate.getEndTime()
|
||||
);
|
||||
|
||||
if (daysInCycle > 0 && caculate.getIrrigationUse() != null) {
|
||||
|
|
@ -259,14 +287,14 @@ public class RiceSupportBalanceService extends ServiceImpl<RiceSupportBalanceMap
|
|||
updateById(riceSupportBalance);
|
||||
} catch (Exception e) {
|
||||
log.error("保存水稻平衡供水明细失败", e);
|
||||
// 这里可以添加异常处理,比如记录日志、发送通知等
|
||||
}
|
||||
}).start();
|
||||
|
||||
// 主线程立即返回,不等待明细计算完成
|
||||
// 主线程立即返回,不等待明细计算完成
|
||||
log.info("水稻平衡供水主表已保存,明细计算正在异步执行");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Page<IcWaterForecast> icPage(RiceSupportBalanceCaculatePageSo pageSo) {
|
||||
LambdaQueryWrapper<IcWaterForecast> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.le(IcWaterForecast::getStartTime,pageSo.getStartTime());
|
||||
|
|
|
|||
|
|
@ -190,6 +190,72 @@ public class LocalDateTimeUtils {
|
|||
return (int) days;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算忽略年份的时间范围内的天数(用于年循环的周期,如生长周期)
|
||||
* 处理跨年情况,如11月15日到次年3月15日
|
||||
*
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 天数(假设为同一年计算)
|
||||
*/
|
||||
public static int calculateDaysIgnoringYear(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
if (startTime == null || endTime == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 将开始和结束时间调整为同一年(比如都调整为2020年)
|
||||
int baseYear = 2020; // 选择一个基准年
|
||||
|
||||
LocalDateTime adjustedStart = startTime.withYear(baseYear);
|
||||
LocalDateTime adjustedEnd = endTime.withYear(baseYear);
|
||||
|
||||
// 如果调整后开始时间在结束时间之后,说明是跨年周期
|
||||
// 如:11月15日(2020年)到3月15日(2020年)实际上应该是11月15日到次年3月15日
|
||||
if (adjustedStart.isAfter(adjustedEnd)) {
|
||||
adjustedEnd = adjustedEnd.plusYears(1); // 结束时间加一年
|
||||
}
|
||||
|
||||
// 计算天数
|
||||
return getTotalDayByRangeDate(adjustedStart, adjustedEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断日期是否在忽略年份的时间范围内
|
||||
*
|
||||
* @param checkDate 检查日期
|
||||
* @param startTime 周期开始时间
|
||||
* @param endTime 周期结束时间
|
||||
* @return 是否在周期内
|
||||
*/
|
||||
public static boolean isDateInCycleIgnoringYear(LocalDateTime checkDate,
|
||||
LocalDateTime startTime,
|
||||
LocalDateTime endTime) {
|
||||
if (checkDate == null || startTime == null || endTime == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 提取月日
|
||||
int checkMonth = checkDate.getMonthValue();
|
||||
int checkDay = checkDate.getDayOfMonth();
|
||||
|
||||
int startMonth = startTime.getMonthValue();
|
||||
int startDay = startTime.getDayOfMonth();
|
||||
|
||||
int endMonth = endTime.getMonthValue();
|
||||
int endDay = endTime.getDayOfMonth();
|
||||
|
||||
// 判断日期是否在周期内
|
||||
if (startMonth < endMonth || (startMonth == endMonth && startDay <= endDay)) {
|
||||
// 不跨年情况
|
||||
return (checkMonth > startMonth || (checkMonth == startMonth && checkDay >= startDay)) &&
|
||||
(checkMonth < endMonth || (checkMonth == endMonth && checkDay <= endDay));
|
||||
} else {
|
||||
// 跨年情况
|
||||
return (checkMonth > startMonth || (checkMonth == startMonth && checkDay >= startDay)) ||
|
||||
(checkMonth < endMonth || (checkMonth == endMonth && checkDay <= endDay));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue