diff --git a/src/main/java/com/gunshi/project/hsz/controller/RiceRqWaterController.java b/src/main/java/com/gunshi/project/hsz/controller/RiceRqWaterController.java new file mode 100644 index 0000000..db3490a --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/controller/RiceRqWaterController.java @@ -0,0 +1,95 @@ +package com.gunshi.project.hsz.controller; + + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gunshi.core.result.R; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import com.gunshi.project.hsz.entity.dto.RiceWaterCaculateDto; +import com.gunshi.project.hsz.entity.so.AttCctvBasePage; +import com.gunshi.project.hsz.entity.so.RiceRqWaterPageSo; +import com.gunshi.project.hsz.entity.vo.RiceRqWaterCaculateVo; +import com.gunshi.project.hsz.model.*; +import com.gunshi.project.hsz.service.RiceRqWaterService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Tag(name = "农业需水预测") +@RestController +@RequestMapping(value="/riceRqWater") +public class RiceRqWaterController { + + + + @Autowired + private RiceRqWaterService riceRqWaterService; + + + @Operation(summary = "分页") + @PostMapping("/page") + public R> page(@RequestBody @Validated RiceRqWaterPageSo page) { + return R.ok(riceRqWaterService.pageQuery(page)); + } + + @Operation(summary = "新增") + @PostMapping("/insert") + public R insert(@Validated(Insert.class) @RequestBody RiceRqWater dto) { + return R.ok(riceRqWaterService.saveData(dto)); + } + + @Operation(summary = "修改") + @PostMapping("/update") + public R update(@Validated(Update.class) @RequestBody RiceRqWater dto) { + return R.ok(riceRqWaterService.updateData(dto)); + } + + @Operation(summary = "删除") + @GetMapping("/del/{id}") + public R del(@Schema(name = "id") @PathVariable("id") Long id) { + return R.ok(riceRqWaterService.delData(id)); + } + + @Operation(summary = "阶段耗水量计算") + @PostMapping("/stage/caculate") + public R> stageCaculate(@RequestBody RiceWaterCaculateDto dto){ + List res = riceRqWaterService.stageCaculate(dto); + return R.ok(res); + } + + @Operation(summary = "综合计算") + @PostMapping("/caculate") + public R caculate(@RequestBody RiceWaterCaculateDto dto){ + RiceRqWaterCaculateVo res = riceRqWaterService.caculate(dto); + return R.ok(res); + } + + + @Operation(summary = "灌区用水量计算") + @PostMapping("/irrigation/caculate") + public R> irrigationCaculate(@RequestBody RiceWaterCaculateDto dto){ + List res = riceRqWaterService.irrigationCaculate(dto); + return R.ok(res); + } + + @Operation(summary = "灌区综合用水量计算-按月份计算") + @PostMapping("/irrigation/caculate/month") + public R> irrigationCaculateMonth(@RequestBody RiceWaterCaculateDto dto){ + List res = riceRqWaterService.irrigationComprehensiveCaculateMonth(dto); + return R.ok(res); + } + + @Operation(summary = "灌区综合用水量计算-按生长周期计算") + @PostMapping("/irrigation/caculate/cycle") + public R> irrigationCaculateCycle(@RequestBody RiceWaterCaculateDto dto){ + List res = riceRqWaterService.irrigationComprehensiveCaculateCycle(dto); + return R.ok(res); + } + +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/dto/RiceWaterCaculateDto.java b/src/main/java/com/gunshi/project/hsz/entity/dto/RiceWaterCaculateDto.java new file mode 100644 index 0000000..34c52d3 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/dto/RiceWaterCaculateDto.java @@ -0,0 +1,16 @@ +package com.gunshi.project.hsz.entity.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.gunshi.project.hsz.model.RiceGrowConfig; +import com.gunshi.project.hsz.model.RiceWaterKi; +import lombok.Data; + +import java.util.List; + +@Data +public class RiceWaterCaculateDto { + + private List riceWaterKis;//灌水定额配置 + + private RiceGrowConfig riceGrowConfig;//水稻生长参数配置表 +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/so/RiceRqWaterPageSo.java b/src/main/java/com/gunshi/project/hsz/entity/so/RiceRqWaterPageSo.java new file mode 100644 index 0000000..88f975f --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/so/RiceRqWaterPageSo.java @@ -0,0 +1,21 @@ +package com.gunshi.project.hsz.entity.so; + +import com.gunshi.db.dto.PageSo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + + +@Data +public class RiceRqWaterPageSo { + + + private PageSo pageSo; + + //方案名称 + private String planName; + + + //相似年 + private Integer year; +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/vo/RiceRqWaterCaculateVo.java b/src/main/java/com/gunshi/project/hsz/entity/vo/RiceRqWaterCaculateVo.java new file mode 100644 index 0000000..315770e --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/vo/RiceRqWaterCaculateVo.java @@ -0,0 +1,20 @@ +package com.gunshi.project.hsz.entity.vo; + + +import com.gunshi.project.hsz.model.RiceWaterForecastCycle; +import com.gunshi.project.hsz.model.RiceWaterForecastMonth; +import com.gunshi.project.hsz.model.RiceWaterKi; +import lombok.Data; + +import java.util.List; + +@Data +public class RiceRqWaterCaculateVo { + + + private List riceWaterKis; + + private List riceWaterForecastCycles; + + private List riceWaterForecastMonths; +} diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceGrowConfigMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceGrowConfigMapper.java new file mode 100644 index 0000000..2885d46 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceGrowConfigMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceGrowConfig; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻生长配置 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceGrowConfigMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceIrrigationUseMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceIrrigationUseMapper.java new file mode 100644 index 0000000..7bf53a8 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceIrrigationUseMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceIrrigationUse; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻灌溉用水 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceIrrigationUseMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceRqWaterMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceRqWaterMapper.java new file mode 100644 index 0000000..cda17ef --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceRqWaterMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceRqWater; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻需水主表 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceRqWaterMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastCycleMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastCycleMapper.java new file mode 100644 index 0000000..c1a7237 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastCycleMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceWaterForecastCycle; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻水分预测周期 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceWaterForecastCycleMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastMonthMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastMonthMapper.java new file mode 100644 index 0000000..ebfc716 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterForecastMonthMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceWaterForecastMonth; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻水分预测月份 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceWaterForecastMonthMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterKiMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterKiMapper.java new file mode 100644 index 0000000..6357d6c --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceWaterKiMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceWaterKi; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 水稻水分需水模系数 + * author: xusan + * date: 2024-09-03 17:46:30 + */ +@Mapper +public interface RiceWaterKiMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java b/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java new file mode 100644 index 0000000..dbe5cf2 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java @@ -0,0 +1,107 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 水稻生长配置实体类 + * + * @author + * @TableName rice_grow_config + */ +@Data +@TableName(value = "rice_grow_config") +public class RiceGrowConfig implements Serializable { + + /** + * 主键 + */ + @TableId(value = "id") + @Schema(description = "主键") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 降雨相似年 + */ + @TableField(value = "year") + @Schema(description = "降雨相似年") + private Integer year; + + /** + * 需水系数 + */ + @TableField(value = "α1") + @Schema(description = "需水系数") + private BigDecimal α1; + + /** + * 生长期水面蒸发量(mm) + */ + @TableField(value = "ed1") + @Schema(description = "生长期水面蒸发量(mm)") + private BigDecimal ed1; + + /** + * 渗漏强度 + */ + @TableField(value = "lk_intensity") + @Schema(description = "渗漏强度") + private BigDecimal lkIntensity; + + /** + * 泡田强度 + */ + @TableField(value = "ka_quota") + @Schema(description = "泡田定额") + private BigDecimal kaQuota; + + /** + * 灌区全部灌溉面积 + */ + @TableField(value = "s_area") + @Schema(description = "灌区全部灌溉面积") + private BigDecimal area; + + /** + * 主表id + */ + @TableField(value = "rice_water_id") + @Schema(description = "主表id") + @NotNull(message = "主表id不能为空", groups = {Insert.class, Update.class}) + private Long riceWaterId; + + /** + * 灌溉周期(天) + */ + @TableField(value = "cycle") + @Schema(description = "灌溉周期(天)") + private Integer cycle; + + /** + * 用水量(mm) + */ + @TableField(value = "water_use") + @Schema(description = "用水量(mm)") + private BigDecimal waterUse; + + /** + * 灌溉用水量(万m³) + */ + @TableField(value = "irrigation_use") + @Schema(description = "灌溉用水量(万m³)") + private BigDecimal irrigationUse; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java b/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java new file mode 100644 index 0000000..eb5150d --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java @@ -0,0 +1,56 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 水稻灌溉用水实体类 + * + * @author + * @TableName rice_irrigation_use + */ +@Data +@TableName(value = "rice_irrigation_use") +public class RiceIrrigationUse implements Serializable { + + /** + * 主键id + */ + @TableId(value = "id") + @Schema(description = "主键id") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 主表id + */ + @TableField(value = "rice_water_id") + @Schema(description = "主表id") + private Long riceWaterId; + + /** + * 月份 + */ + @TableField(value = "month") + @Schema(description = "月份") + @NotNull(message = "月份不能为空", groups = {Insert.class, Update.class}) + private Integer month; + + /** + * 灌溉用水量 + */ + @TableField(value = "irrigation_use") + @Schema(description = "用水量") + private BigDecimal irrigationUse; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java b/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java new file mode 100644 index 0000000..c729bdc --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java @@ -0,0 +1,84 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 水稻需水主表实体类 + * + * @author + * @TableName rice_rq_water + */ +@Data +@TableName(value = "rice_rq_water") +public class RiceRqWater implements Serializable { + + /** + * 主键ID + */ + @TableId(value = "id") + @Schema(description = "主键ID") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 方案名称 + */ + @TableField(value = "plan_name") + @Schema(description = "方案名称") + @NotNull(message = "方案名称不能为空", groups = {Insert.class, Update.class}) + private String planName; + + /** + * 需水总量 + */ + @TableField(value = "req_water") + @Schema(description = "需水总量") + private BigDecimal reqWater; + + /** + * 制定时间 + */ + @TableField(value = "create_time") + @Schema(description = "制定时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + /** + * 制定人 + */ + @TableField(value = "create_name") + @Schema(description = "制定人") + private String createName; + + @TableField(value = "year") + @Schema(description = "预测年度") + private Integer year; + + + @TableField(exist = false) + private RiceGrowConfig riceGrowConfig;//水稻生长参数配置表 + + @TableField(exist = false) + private List riceWaterKis;//灌水定额配置 + + @TableField(exist = false) + private List riceWaterForecastMonths;//需水预测-按月份 + + @TableField(exist = false) + private List riceWaterForecastCycles;//需水预测-按周期 +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java new file mode 100644 index 0000000..04a5f0f --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java @@ -0,0 +1,63 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 水稻水分预测周期实体类 + * + * @author + * @TableName rice_water_forecast_cycle + */ +@Data +@TableName(value = "rice_water_forecast_cycle") +public class RiceWaterForecastCycle implements Serializable { + + /** + * 主键id + */ + @TableId(value = "id") + @Schema(description = "主键id") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 主表id + */ + @TableField(value = "rice_water_id") + @Schema(description = "主表id") + private Long riceWaterId; + + /** + * 灌溉周期 + */ + @TableField(value = "rice_grow_stage") + @Schema(description = "灌溉周期") + @NotNull(message = "灌溉周期不能为空", groups = {Insert.class, Update.class}) + private String riceGrowStage; + + /** + * 灌溉周期排序 + */ + @TableField(value = "_order") + @Schema(description = "灌溉周期排序") + private Integer order; + + /** + * 灌溉用水量 + */ + @TableField(value = "irrigation_use") + @Schema(description = "灌溉用水量") + private BigDecimal irrigationUse; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java new file mode 100644 index 0000000..28d1be3 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java @@ -0,0 +1,56 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 水稻水分预测月份实体类 + * + * @author + * @TableName rice_water_forecast_month + */ +@Data +@TableName(value = "rice_water_forecast_month") +public class RiceWaterForecastMonth implements Serializable { + + /** + * 主键id + */ + @TableId(value = "id") + @Schema(description = "主键id") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 月份 + */ + @TableField(value = "month") + @Schema(description = "月份") + @NotNull(message = "月份不能为空", groups = {Insert.class, Update.class}) + private Integer month; + + /** + * 灌溉用水量 + */ + @TableField(value = "irrigation_use") + @Schema(description = "灌溉用水量") + private BigDecimal irrigationUse; + + /** + * 主表id + */ + @TableField(value = "rice_water_id") + @Schema(description = "主表id") + private Long riceWaterId; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java new file mode 100644 index 0000000..196372b --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java @@ -0,0 +1,89 @@ +package com.gunshi.project.hsz.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.gunshi.project.hsz.common.validate.markers.Insert; +import com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * 水稻水分需水模系数实体类 + * + * @author + * @TableName rice_water_ki + */ +@Data +@TableName(value = "rice_water_ki") +public class RiceWaterKi implements Serializable { + + /** + * 主键 + */ + @TableId(value = "id") + @Schema(description = "主键") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 主表id + */ + @TableField(value = "rice_water_id") + @Schema(description = "主表id") + private Long riceWaterId; + + /** + * 水稻生育阶段 + */ + @TableField(value = "rice_grow_stage") + @Schema(description = "水稻生育阶段") + @NotNull(message = "水稻生育阶段不能为空", groups = {Insert.class, Update.class}) + private String riceGrowStage; + + /** + * 开始日期 + */ + @TableField(value = "start_time") + @Schema(description = "开始日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime startTime; + + /** + * 结束日期 + */ + @TableField(value = "end_time") + @Schema(description = "结束日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime endTime; + + /** + * 阶段天数 + */ + @TableField(value = "days") + @Schema(description = "阶段天数") + private Integer days; + + /** + * 需水模系数 + */ + @TableField(value = "ki") + @Schema(description = "需水模系数") + private BigDecimal ki; + + /** + * 阶段耗水量(mm) + */ + @TableField(value = "water_rq_stage") + @Schema(description = "阶段耗水量(mm)") + private BigDecimal waterRqStage; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceGrowConfigService.java b/src/main/java/com/gunshi/project/hsz/service/RiceGrowConfigService.java new file mode 100644 index 0000000..6eed42b --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceGrowConfigService.java @@ -0,0 +1,32 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.RiceGrowConfigMapper; +import com.gunshi.project.hsz.model.RiceGrowConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 描述: 水稻生长配置 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceGrowConfigService extends ServiceImpl { + + public RiceGrowConfig selectByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceGrowConfig::getRiceWaterId, riceWaterId); + return this.baseMapper.selectOne(queryWrapper); + } + + public void removeByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceGrowConfig::getRiceWaterId, riceWaterId); + this.remove(queryWrapper); + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceIrrigationUseService.java b/src/main/java/com/gunshi/project/hsz/service/RiceIrrigationUseService.java new file mode 100644 index 0000000..2aadd57 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceIrrigationUseService.java @@ -0,0 +1,34 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.RiceIrrigationUseMapper; +import com.gunshi.project.hsz.model.RiceIrrigationUse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 描述: 水稻灌溉用水 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceIrrigationUseService extends ServiceImpl { + + public List selectByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceIrrigationUse::getRiceWaterId, riceWaterId); + return this.baseMapper.selectList(queryWrapper); + } + + public void removeByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceIrrigationUse::getRiceWaterId, riceWaterId); + this.remove(queryWrapper); + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java b/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java new file mode 100644 index 0000000..087dce9 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java @@ -0,0 +1,744 @@ +package com.gunshi.project.hsz.service; + +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 com.gunshi.project.hsz.entity.dto.RiceWaterCaculateDto; +import com.gunshi.project.hsz.entity.so.RiceRqWaterPageSo; +import com.gunshi.project.hsz.entity.vo.RiceRqWaterCaculateVo; +import com.gunshi.project.hsz.entity.vo.TyYearRainfallVo; +import com.gunshi.project.hsz.mapper.RiceRqWaterMapper; +import com.gunshi.project.hsz.model.*; +import com.ruoyi.common.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 描述: 水稻需水主表 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceRqWaterService extends ServiceImpl { + + + @Autowired + private RiceGrowConfigService riceGrowConfigService; + + @Autowired + private RiceIrrigationUseService riceIrrigationUseService; + + @Autowired + private RiceWaterForecastCycleService riceWaterForecastCycleService; + + @Autowired + private RiceWaterForecastMonthService riceWaterForecastMonthService; + + @Autowired + private RiceWaterKiService riceWaterKiService; + + public Page pageQuery(RiceRqWaterPageSo page) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if(page.getYear() != null){ + queryWrapper.eq(RiceRqWater::getYear,page.getYear()); + } + + if(!StringUtils.isBlank(page.getPlanName())){ + queryWrapper.like(RiceRqWater::getPlanName,page.getPlanName()); + } + Page riceRqWaterPage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper); + List records = riceRqWaterPage.getRecords(); + for (RiceRqWater record : records) { + //灌水定额配置 + record.setRiceWaterKis(riceWaterKiService.selectByRiceWaterId(record.getId())); + //水稻生长系数配置 + record.setRiceGrowConfig(riceGrowConfigService.selectByRiceWaterId(record.getId())); + //按月份 + record.setRiceWaterForecastMonths(riceWaterForecastMonthService.selectByRiceWaterId(record.getId())); + //按生长周期 + record.setRiceWaterForecastCycles(riceWaterForecastCycleService.selectByRiceWaterId(record.getId())); + } + return riceRqWaterPage; + } + + public RiceRqWater saveData(RiceRqWater dto) { + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + List riceWaterKis = dto.getRiceWaterKis(); + List riceWaterForecastCycles = dto.getRiceWaterForecastCycles(); + List riceWaterForecastMonths = dto.getRiceWaterForecastMonths(); + save(dto); + riceGrowConfig.setRiceWaterId(dto.getId()); + riceWaterKis.stream().forEach(o ->{ + o.setRiceWaterId(dto.getId()); + }); + riceWaterForecastCycles.stream().forEach(o ->{ + o.setRiceWaterId(dto.getId()); + }); + riceWaterForecastMonths.stream().forEach(o ->{ + o.setRiceWaterId(dto.getId()); + }); + riceWaterKiService.saveBatch(riceWaterKis); + riceGrowConfigService.save(riceGrowConfig); + riceWaterForecastCycleService.saveBatch(riceWaterForecastCycles); + riceWaterForecastMonthService.saveBatch(riceWaterForecastMonths); + return dto; + } + + public RiceRqWater updateData(RiceRqWater dto) { + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + List riceWaterKis = dto.getRiceWaterKis(); + List riceWaterForecastCycles = dto.getRiceWaterForecastCycles(); + List riceWaterForecastMonths = dto.getRiceWaterForecastMonths(); + updateById(dto); + riceWaterKiService.updateBatchById(riceWaterKis); + riceWaterForecastCycleService.updateBatchById(riceWaterForecastCycles); + riceWaterForecastMonthService.updateBatchById(riceWaterForecastMonths); + riceGrowConfigService.updateById(riceGrowConfig); + return dto; + } + + public Boolean delData(Long id) { + removeById(id); + riceWaterKiService.removeByRiceWaterId(id); + riceGrowConfigService.removeByRiceWaterId(id); + riceIrrigationUseService.removeByRiceWaterId(id); + riceWaterForecastCycleService.removeByRiceWaterId(id); + riceWaterForecastMonthService.removeByRiceWaterId(id); + return true; + } + + public List stageCaculate(RiceWaterCaculateDto dto) { + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + List riceWaterKis = dto.getRiceWaterKis(); + orderByStartTimeAsc(riceWaterKis); + // 早稻需水系数 + BigDecimal α1 = riceGrowConfig.getΑ1(); + if(α1 == null){ + throw new IllegalArgumentException("早稻需水系数不能为空"); + } + // 渗漏强度 + BigDecimal lkIntensity = riceGrowConfig.getLkIntensity(); + if(lkIntensity == null){ + throw new IllegalArgumentException("渗漏强度不能为空"); + } + // 生长期水面蒸发量(mm) + BigDecimal ed1 = riceGrowConfig.getEd1(); + if(ed1 == null){ + throw new IllegalArgumentException("生长期水面蒸发量不能为空"); + } + for (RiceWaterKi riceWaterKi : riceWaterKis) { + // 计算阶段耗水量 + if(riceWaterKi.getRiceGrowStage().contains("泡田")){ + riceWaterKi.setKi(riceGrowConfig.getΑ1());//需水系数 + riceWaterKi.setWaterRqStage(riceGrowConfig.getKaQuota());//泡田定额 + continue; + } + BigDecimal waterRqStage = calculateWaterRqStage(riceWaterKi, α1, ed1, lkIntensity); + riceWaterKi.setWaterRqStage(waterRqStage.setScale(1,RoundingMode.UP)); + } + + return riceWaterKis; + } + + /** + * 计算阶段耗水量 + * 公式:ki * α1 * ed1 + days * lkIntensity + */ + private BigDecimal calculateWaterRqStage(RiceWaterKi riceWaterKi, BigDecimal α1, + BigDecimal ed1, BigDecimal lkIntensity) { + // 获取需水模系数 + BigDecimal ki = riceWaterKi.getKi(); + if(ki == null){ + throw new IllegalArgumentException("需水模型系数不能为空"); + } + // 计算天数(如果days为空,则根据开始结束日期计算) + Integer days = riceWaterKi.getDays(); + if (days == null && riceWaterKi.getStartTime() != null && riceWaterKi.getEndTime() != null) { + days = calculateDaysBetween(riceWaterKi.getStartTime(), riceWaterKi.getEndTime()); + riceWaterKi.setDays(days); // 同时设置回实体中 + } + if (days == null) { + days = 0; + } + + + // 计算公式:ki * α1 * ed1 + days * lkIntensity + BigDecimal part1 = ki.multiply(α1).multiply(ed1); + BigDecimal part2 = new BigDecimal(days).multiply(lkIntensity); + + return part1.add(part2); + } + + /** + * 计算两个LocalDateTime之间的天数(包含开始和结束日期) + * 例如:2025-04-26 ~ 2025-05-06 = 11天 + */ + private Integer calculateDaysBetween(LocalDateTime startTime, LocalDateTime endTime) { + if (startTime == null || endTime == null) { + return 0; + } + + // 使用LocalDate来计算天数,忽略时间部分 + long days = java.time.temporal.ChronoUnit.DAYS.between( + startTime.toLocalDate(), + endTime.toLocalDate() + ); + + // 因为包含开始和结束日期,所以需要+1 + return (int) days + 1; + } + + @Autowired + private TyYearRainfallService tyYearRainfallService; + + public List irrigationCaculate(RiceWaterCaculateDto dto) { + List riceWaterKis = dto.getRiceWaterKis(); + List res = new ArrayList<>(); + orderByStartTimeAsc(riceWaterKis); + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + Integer year = riceGrowConfig.getYear();//相似年 + List tyYearRainfallVos = tyYearRainfallService.queryList(); + List collect = tyYearRainfallVos.stream().filter(o -> { + return o.getYear().equals(year); + }).collect(Collectors.toList()); + if(collect == null || collect.isEmpty()){ + throw new IllegalArgumentException("对不起,没有该年份的降雨资料"); + } + TyYearRainfallVo tyYearRainfallVo = collect.get(0); + List list = tyYearRainfallVo.getList();//获取月份的降雨资料 + //泡田定额 + BigDecimal kaQuota = riceGrowConfig.getKaQuota(); + + // 泡田期是第一个元素 + RiceWaterKi kaPeriod = riceWaterKis.get(0); + LocalDateTime kaStartTime = kaPeriod.getStartTime(); + LocalDateTime kaEndTime = kaPeriod.getEndTime(); + int totalKaDays = calculateTotalKaDays(kaStartTime, kaEndTime); + + // 生育期数据(排除泡田期) + List growPeriods = riceWaterKis.subList(1, riceWaterKis.size()); + + // 用于存储去重后的月份(1-12) + Set monthSet = new HashSet<>(); + + // 添加泡田期的月份 + monthSet.add(kaStartTime.getMonthValue()); + monthSet.add(kaEndTime.getMonthValue()); + + // 遍历集合,提取每个元素的 startTime 和 endTime 对应的月份 + for (RiceWaterKi riceWaterKi : riceWaterKis) { + LocalDateTime start = riceWaterKi.getStartTime(); + LocalDateTime end = riceWaterKi.getEndTime(); + + if (start != null) { + monthSet.add(start.getMonthValue()); + } + if (end != null) { + monthSet.add(end.getMonthValue()); + } + } + + // 将去重后的月份转为列表并按从小到大排序 + List sortedMonths = monthSet.stream() + .sorted() + .collect(Collectors.toList()); + + for (Integer sortedMonth : sortedMonths) { + RiceIrrigationUse riceIrrigationUse = new RiceIrrigationUse(); + riceIrrigationUse.setMonth(sortedMonth); + + BigDecimal irrigationVolume = BigDecimal.ZERO; + + // 计算泡田期在当前月份的耗水量 + if (isMonthInKaPeriod(sortedMonth, kaStartTime, kaEndTime)) { + int kaDaysInMonth = calculateKaDaysInMonth(kaStartTime, kaEndTime, sortedMonth); + BigDecimal kaConsumption = kaQuota.divide(BigDecimal.valueOf(totalKaDays), 100, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(kaDaysInMonth)); + irrigationVolume = irrigationVolume.add(kaConsumption); + } + + // 修正:计算生育期在当前月份的总耗水量(按Excel逻辑) + BigDecimal growConsumption = calculateGrowConsumptionForMonth(sortedMonth, growPeriods); + irrigationVolume = irrigationVolume.add(growConsumption); + + // 计算该月份所有生育阶段的总有效降雨量 + BigDecimal monthlyRainfall = calculateTotalEffectiveRainfallForMonth(sortedMonth, growPeriods, list); + irrigationVolume = irrigationVolume.subtract(monthlyRainfall); + + + // 如果计算结果是负数,则设为0 +// if (irrigationVolume.compareTo(BigDecimal.ZERO) < 0) { +// irrigationVolume = BigDecimal.ZERO; +// } + + // 保留1位小数 + irrigationVolume = irrigationVolume.setScale(2, RoundingMode.HALF_UP); + + riceIrrigationUse.setIrrigationUse(irrigationVolume); + res.add(riceIrrigationUse); + } + return res; + } + + + /** + * 计算指定月份生育期的总耗水量(按Excel逻辑) + */ + private BigDecimal calculateGrowConsumptionForMonth(int month, List growPeriods) { + BigDecimal totalConsumption = BigDecimal.ZERO; + + for (RiceWaterKi growPeriod : growPeriods) { + LocalDateTime startTime = growPeriod.getStartTime(); + LocalDateTime endTime = growPeriod.getEndTime(); + + // 检查该阶段是否包含这个月份 + if (isMonthInPeriod(month, startTime, endTime)) { + // 获取阶段在该月份的天数 + int daysInMonth = calculateDaysInMonthForPeriod(startTime, endTime, month); + + if (daysInMonth > 0) { + // 判断阶段是否跨月份 + List monthsInStage = getMonthsInPeriod(startTime, endTime); + + if (monthsInStage.size() == 1) { + // 不跨月份:直接使用完整耗水量 + totalConsumption = totalConsumption.add(growPeriod.getWaterRqStage()); + } else { + // 跨月份:按天数比例分配耗水量 + BigDecimal dailyConsumption = growPeriod.getWaterRqStage() + .divide(BigDecimal.valueOf(growPeriod.getDays()), 10, RoundingMode.HALF_UP); + BigDecimal monthlyConsumption = dailyConsumption.multiply(BigDecimal.valueOf(daysInMonth)); + totalConsumption = totalConsumption.add(monthlyConsumption); + } + } + } + } + + return totalConsumption; + } + + /** + * 计算指定月份所有生育阶段的总有效降雨量 + */ + private BigDecimal calculateTotalEffectiveRainfallForMonth(int month, List growPeriods, + List rainfallList) { + BigDecimal totalRainfall = BigDecimal.ZERO; + + for (RiceWaterKi growPeriod : growPeriods) { + LocalDateTime startTime = growPeriod.getStartTime(); + LocalDateTime endTime = growPeriod.getEndTime(); + + // 检查该阶段是否包含这个月份 + if (isMonthInPeriod(month, startTime, endTime)) { + // 使用getMonthlyRainfall方法计算该阶段在该月份的有效降雨量 + BigDecimal stageRainfall = getMonthlyRainfall(rainfallList, month, startTime, endTime); + totalRainfall = totalRainfall.add(stageRainfall); + } + } + + return totalRainfall.setScale(1, RoundingMode.HALF_UP); + } + + /** + * 判断月份是否在阶段时间内 + */ + private boolean isMonthInPeriod(int month, LocalDateTime startTime, LocalDateTime endTime) { + if (startTime == null || endTime == null) { + return false; + } + + LocalDate startDate = startTime.toLocalDate(); + LocalDate endDate = endTime.toLocalDate(); + LocalDate current = startDate; + + while (!current.isAfter(endDate)) { + if (current.getMonthValue() == month) { + return true; + } + current = current.plusDays(1); + } + + return false; + } + + /** + * 获取第一个包含生育期的月份(只从生育期中获取) + */ + private int getFirstGrowMonth(List growPeriods) { + return growPeriods.stream() + .map(ki -> ki.getStartTime().getMonthValue()) + .min(Integer::compareTo) + .orElseThrow(() -> new IllegalArgumentException("未找到生育期数据")); + } + + /** + * 查找泡田期数据 + */ + private RiceWaterKi findKaPeriod(List riceWaterKis) { + return riceWaterKis.stream() + .filter(ki -> ki.getRiceGrowStage().contains("泡田")) + .findFirst() + .orElse(null); + } + + /** + * 从降雨资料中获取指定月份的降雨量(简单版本) + */ + private BigDecimal getMonthlyRainfall(List rainfallList, int month) { + if (rainfallList == null) { + return BigDecimal.ZERO; + } + + return rainfallList.stream() + .filter(rainfall -> rainfall.getMonth() != null && rainfall.getMonth() == month) + .findFirst() + .map(TyYearRainfall::getDrp) + .orElse(BigDecimal.ZERO); + } + + + + + + + /** + * 计算阶段在指定月份的天数 + */ + private int calculateDaysInMonthForPeriod(LocalDateTime startTime, LocalDateTime endTime, int targetMonth) { + if (startTime == null || endTime == null) { + return 0; + } + + LocalDate startDate = startTime.toLocalDate(); + LocalDate endDate = endTime.toLocalDate(); + LocalDate current = startDate; + int daysInTargetMonth = 0; + + while (!current.isAfter(endDate)) { + if (current.getMonthValue() == targetMonth) { + daysInTargetMonth++; + } + current = current.plusDays(1); + } + + return daysInTargetMonth; + } + + + /** + * 判断月份是否在泡田期内 + */ + private boolean isMonthInKaPeriod(int month, LocalDateTime kaStart, LocalDateTime kaEnd) { + int startMonth = kaStart.getMonthValue(); + int endMonth = kaEnd.getMonthValue(); + return month >= startMonth && month <= endMonth; + } + + /** + * 计算泡田期在当前月份的天数 + */ + private int calculateKaDaysInMonth(LocalDateTime kaStart, LocalDateTime kaEnd, int targetMonth) { + int startMonth = kaStart.getMonthValue(); + int endMonth = kaEnd.getMonthValue(); + + // 如果整个泡田期都在目标月份内 + if (startMonth == targetMonth && endMonth == targetMonth) { + return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), kaEnd.toLocalDate()) + 1; + } + + // 如果泡田期开始时间在目标月份,结束时间在下个月 + if (startMonth == targetMonth && endMonth > targetMonth) { + LocalDate lastDayOfMonth = kaStart.toLocalDate().withDayOfMonth(kaStart.toLocalDate().lengthOfMonth()); + return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), lastDayOfMonth) + 1; + } + + // 如果泡田期结束时间在目标月份,开始时间在上个月 + if (endMonth == targetMonth && startMonth < targetMonth) { + LocalDate firstDayOfMonth = kaEnd.toLocalDate().withDayOfMonth(1); + return (int) java.time.temporal.ChronoUnit.DAYS.between(firstDayOfMonth, kaEnd.toLocalDate()) + 1; + } + + return 0; + } + + /** + * 计算泡田期总天数 + */ + private int calculateTotalKaDays(LocalDateTime kaStart, LocalDateTime kaEnd) { + return (int) java.time.temporal.ChronoUnit.DAYS.between(kaStart.toLocalDate(), kaEnd.toLocalDate()) + 1; + } + + + + /** + * 计算RiceWaterKi在当前月份内的天数 + */ + private int calculateDaysInMonth(RiceWaterKi ki, int targetMonth) { + LocalDateTime start = ki.getStartTime(); + LocalDateTime end = ki.getEndTime(); + + int startMonth = start.getMonthValue(); + int endMonth = end.getMonthValue(); + + // 如果整个时间段都在目标月份内 + if (startMonth == targetMonth && endMonth == targetMonth) { + return ki.getDays(); + } + + // 如果开始时间在目标月份,结束时间在下个月 + if (startMonth == targetMonth && endMonth > targetMonth) { + LocalDate lastDayOfMonth = start.toLocalDate().withDayOfMonth(start.toLocalDate().lengthOfMonth()); + return (int) java.time.temporal.ChronoUnit.DAYS.between(start.toLocalDate(), lastDayOfMonth) + 1; + } + + // 如果结束时间在目标月份,开始时间在上个月 + if (endMonth == targetMonth && startMonth < targetMonth) { + LocalDate firstDayOfMonth = end.toLocalDate().withDayOfMonth(1); + return (int) java.time.temporal.ChronoUnit.DAYS.between(firstDayOfMonth, end.toLocalDate()) + 1; + } + + // 如果时间段跨越整个月份 + if (startMonth < targetMonth && endMonth > targetMonth) { + LocalDate firstDayOfMonth = LocalDate.of(start.getYear(), targetMonth, 1); + return firstDayOfMonth.lengthOfMonth(); + } + + return 0; + } + + + /** + * 将ki的数据按照月份从小到大排序 + */ + private void orderByStartTimeAsc(List riceWaterKis) { + Collections.sort(riceWaterKis, (ki1, ki2) -> { + LocalDateTime time1 = ki1.getStartTime(); + LocalDateTime time2 = ki2.getStartTime(); + if (time1 == null) return -1; + if (time2 == null) return 1; + return time1.compareTo(time2); + }); + } + + public List irrigationComprehensiveCaculateMonth(RiceWaterCaculateDto dto) { + List riceIrrigationUses = irrigationCaculate(dto);//获取灌区水稻用水量 + List res = new ArrayList<>(); + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + //灌溉区面积(亩) + BigDecimal sArea = riceGrowConfig.getArea(); + + for (RiceIrrigationUse riceIrrigationUse : riceIrrigationUses) { + RiceWaterForecastMonth entity = new RiceWaterForecastMonth(); + entity.setMonth(riceIrrigationUse.getMonth()); + + BigDecimal irrigationUse = riceIrrigationUse.getIrrigationUse(); + // 计算公式:2/3 * irrigationUse * sArea / 10000 + BigDecimal value = new BigDecimal("2") + .divide(new BigDecimal("3"), 10, RoundingMode.HALF_UP) // 2/3,保留10位小数 + .multiply(irrigationUse) + .multiply(sArea) + .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP); // 除以10000,保留2位小数 + + entity.setIrrigationUse(value); + res.add(entity); + } + return res; + } + + + /** + * 获取指定月份的总天数 + */ + private int getTotalDaysInMonth(int year, int month) { + LocalDate date = LocalDate.of(year, month, 1); + return date.lengthOfMonth(); + } + + /** + * 获取时间段内包含的月份 + */ + private List getMonthsInPeriod(LocalDateTime startTime, LocalDateTime endTime) { + List months = new ArrayList<>(); + if (startTime == null || endTime == null) { + return months; + } + + LocalDate current = startTime.toLocalDate(); + LocalDate end = endTime.toLocalDate(); + + while (!current.isAfter(end)) { + int month = current.getMonthValue(); + if (!months.contains(month)) { + months.add(month); + } + current = current.plusDays(1); + } + + // 按月份顺序排序 + Collections.sort(months); + return months; + } + + public List irrigationComprehensiveCaculateCycle(RiceWaterCaculateDto dto) { + List riceWaterKis = dto.getRiceWaterKis(); + orderByStartTimeAsc(riceWaterKis); + RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + BigDecimal kaQuota = riceGrowConfig.getKaQuota();//泡田定额 + Integer year = riceGrowConfig.getYear();//相似年 + BigDecimal sArea = riceGrowConfig.getArea(); + List tyYearRainfallVos = tyYearRainfallService.queryList(); + List collect = tyYearRainfallVos.stream().filter(o -> { + return o.getYear().equals(year); + }).collect(Collectors.toList()); + if(collect == null || collect.isEmpty()){ + throw new IllegalArgumentException("对不起,没有该年份的降雨资料"); + } + TyYearRainfallVo tyYearRainfallVo = collect.get(0); + List rainfallList = tyYearRainfallVo.getList();//获取月份的降雨资料 + List res = new ArrayList<>(); + + for (int i = 0; i < riceWaterKis.size(); i++) { + RiceWaterKi riceWaterKi = riceWaterKis.get(i); + RiceWaterForecastCycle data = new RiceWaterForecastCycle(); + data.setRiceGrowStage(riceWaterKi.getRiceGrowStage()); + data.setOrder(i + 1); + + //泡田期为定值,泡田定额 + if(riceWaterKi.getRiceGrowStage().contains("泡田")){ + data.setIrrigationUse(kaQuota); + data.setRiceGrowStage("泡田期"); + res.add(data); + } else { + LocalDateTime startTime = riceWaterKi.getStartTime(); + LocalDateTime endTime = riceWaterKi.getEndTime(); + BigDecimal irrigationUse = calculateIrrigationUse(riceWaterKi, rainfallList, startTime, endTime); + data.setIrrigationUse(irrigationUse.setScale(2,RoundingMode.UP)); + res.add(data); + } + } + + for (RiceWaterForecastCycle re : res) { + BigDecimal irrigationUse = re.getIrrigationUse(); + + BigDecimal value = new BigDecimal("2") + .divide(new BigDecimal("3"), 10, RoundingMode.HALF_UP) // 2/3,保留10位小数 + .multiply(irrigationUse) + .multiply(sArea) + .divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP); // 除以10000,保留2位小数 + re.setIrrigationUse(value); + } + return res; + } + + /** + * 计算非泡田期的灌溉用水量 + */ + private BigDecimal calculateIrrigationUse(RiceWaterKi riceWaterKi, List rainfallList, + LocalDateTime startTime, LocalDateTime endTime) { + // 阶段用水量(从waterRqStage获取) + BigDecimal stageWaterUse = riceWaterKi.getWaterRqStage(); + if (stageWaterUse == null) { + stageWaterUse = BigDecimal.ZERO; + } + + // 计算有效降雨量 + BigDecimal effectiveRainfall = calculateEffectiveRainfall(rainfallList, startTime, endTime); + + // 灌溉用水量 = 阶段用水量 - 有效降雨量 + BigDecimal irrigationUse = stageWaterUse.subtract(effectiveRainfall); + + // 确保不会出现负值 + return irrigationUse.compareTo(BigDecimal.ZERO) > 0 ? irrigationUse : BigDecimal.ZERO; + } + + /** + * 计算阶段内的有效降雨量 + */ + private BigDecimal calculateEffectiveRainfall(List rainfallList, + LocalDateTime stageStartTime, LocalDateTime stageEndTime) { + BigDecimal totalEffectiveRainfall = BigDecimal.ZERO; + + // 获取阶段跨越的月份 + Set months = getMonthsInPeriodSet(stageStartTime, stageEndTime); + + for (Integer month : months) { + BigDecimal monthlyRainfall = getMonthlyRainfall(rainfallList, month, stageStartTime, stageEndTime); + totalEffectiveRainfall = totalEffectiveRainfall.add(monthlyRainfall); + } + + return totalEffectiveRainfall; + } + + /** + * 获取阶段跨越的月份集合 + */ + private Set getMonthsInPeriodSet(LocalDateTime startTime, LocalDateTime endTime) { + Set months = new HashSet<>(); + LocalDateTime current = startTime; + + while (!current.isAfter(endTime)) { + months.add(current.getMonthValue()); + current = current.plusMonths(1).withDayOfMonth(1); + } + + return months; + } + + /** + * 从降雨资料中获取指定月份的降雨量,并根据阶段实际使用天数进行调整 + */ + private BigDecimal getMonthlyRainfall(List rainfallList, int month, + LocalDateTime stageStartTime, LocalDateTime stageEndTime) { + if (rainfallList == null || stageStartTime == null || stageEndTime == null) { + return BigDecimal.ZERO; + } + + // 获取原始月降雨量 + BigDecimal originalRainfall = rainfallList.stream() + .filter(rainfall -> rainfall.getMonth() != null && rainfall.getMonth() == month) + .findFirst() + .map(TyYearRainfall::getDrp) + .orElse(BigDecimal.ZERO); + + // 计算阶段在该月份的实际使用天数 + int daysInMonth = calculateDaysInMonthForPeriod(stageStartTime, stageEndTime, month); + int totalDaysInMonth = getTotalDaysInMonth(stageStartTime.getYear(), month); + + if (daysInMonth > 0 && totalDaysInMonth > 0) { + // 按实际使用天数比例计算有效降雨量 + return originalRainfall + .multiply(BigDecimal.valueOf(daysInMonth)) + .divide(BigDecimal.valueOf(totalDaysInMonth), 10, RoundingMode.HALF_UP); + } + + return BigDecimal.ZERO; + } + + public RiceRqWaterCaculateVo caculate(RiceWaterCaculateDto dto) { + //先计算阶段耗水量 + RiceRqWaterCaculateVo vo = new RiceRqWaterCaculateVo(); + List riceWaterKis = stageCaculate(dto); + dto.setRiceWaterKis(riceWaterKis); + //计算灌区水稻用水量-按月份 + List riceWaterForecastMonths = irrigationComprehensiveCaculateMonth(dto); + //计算灌区水稻用水量-按周期 + List riceWaterForecastCycles = irrigationComprehensiveCaculateCycle(dto); + vo.setRiceWaterKis(riceWaterKis); + vo.setRiceWaterForecastMonths(riceWaterForecastMonths); + vo.setRiceWaterForecastCycles(riceWaterForecastCycles); + return vo; + + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastCycleService.java b/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastCycleService.java new file mode 100644 index 0000000..93d908f --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastCycleService.java @@ -0,0 +1,35 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.RiceWaterForecastCycleMapper; +import com.gunshi.project.hsz.model.RiceWaterForecastCycle; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 描述: 水稻水分预测周期 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceWaterForecastCycleService extends ServiceImpl { + + public List selectByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterForecastCycle::getRiceWaterId, riceWaterId); + queryWrapper.orderByAsc(RiceWaterForecastCycle::getOrder); + return this.baseMapper.selectList(queryWrapper); + } + + public void removeByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterForecastCycle::getRiceWaterId, riceWaterId); + this.remove(queryWrapper); + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastMonthService.java b/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastMonthService.java new file mode 100644 index 0000000..a804621 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceWaterForecastMonthService.java @@ -0,0 +1,34 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.RiceWaterForecastMonthMapper; +import com.gunshi.project.hsz.model.RiceWaterForecastMonth; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 描述: 水稻水分预测月份 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceWaterForecastMonthService extends ServiceImpl { + + public List selectByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterForecastMonth::getRiceWaterId, riceWaterId); + return this.baseMapper.selectList(queryWrapper); + } + + public void removeByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterForecastMonth::getRiceWaterId, riceWaterId); + this.baseMapper.delete(queryWrapper); + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceWaterKiService.java b/src/main/java/com/gunshi/project/hsz/service/RiceWaterKiService.java new file mode 100644 index 0000000..eb81138 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceWaterKiService.java @@ -0,0 +1,34 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.RiceWaterKiMapper; +import com.gunshi.project.hsz.model.RiceWaterKi; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 描述: 水稻水分需水模系数 + * author: xusan + * date: 2024-09-04 13:42:40 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceWaterKiService extends ServiceImpl { + + public List selectByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterKi::getRiceWaterId, riceWaterId); + return this.baseMapper.selectList(queryWrapper); + } + + public void removeByRiceWaterId(Long riceWaterId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceWaterKi::getRiceWaterId, riceWaterId); + this.baseMapper.delete(queryWrapper); + } +} \ No newline at end of file