From 7464c7af87cbac46bacaaa46e61788e20e5f6357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=BE=E5=AF=8C=E6=96=8C?= Date: Fri, 29 Aug 2025 12:41:06 +0800 Subject: [PATCH] =?UTF-8?q?feat=20(farm):=20=E5=9F=BA=E5=9C=B0,=E5=9C=B0?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增,修改,删除时添加面积限制 --- .../module/farm/enums/ErrorCodeConstants.java | 2 + .../service/baseinfo/BaseInfoServiceImpl.java | 76 ++++++++++++------- .../service/plotinfo/PlotInfoServiceImpl.java | 56 +++++++++++++- .../productionplan/ProductionPlanService.java | 37 +++++++++ .../ProductionPlanServiceImpl.java | 48 +++++++++++- 5 files changed, 185 insertions(+), 34 deletions(-) diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/enums/ErrorCodeConstants.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/enums/ErrorCodeConstants.java index e7b0cda9..0518166d 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/enums/ErrorCodeConstants.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/enums/ErrorCodeConstants.java @@ -117,4 +117,6 @@ public interface ErrorCodeConstants { // ========== 设备报警 1_050_035_000 ========== ErrorCode TWO_DICT_NOT_EXISTS = new ErrorCode(1_050_035_000, "字典不存在"); + ErrorCode PLOT_AREA_ERRORS = new ErrorCode(1_050_036_000, "地块面积总和大于基地面积"); + } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/baseinfo/BaseInfoServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/baseinfo/BaseInfoServiceImpl.java index 99f37c16..80a27d8f 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/baseinfo/BaseInfoServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/baseinfo/BaseInfoServiceImpl.java @@ -13,9 +13,9 @@ import cn.iocoder.yudao.module.farm.dal.mysql.baseinfo.BaseInfoMapper; import cn.iocoder.yudao.module.farm.dal.mysql.gridinfo.GridInfoMapper; import cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement.PersonnelManagementMapper; import cn.iocoder.yudao.module.farm.dal.mysql.plotinfo.PlotInfoMapper; -import cn.iocoder.yudao.module.farm.dal.mysql.productionplan.ProductionPlanMapper; import cn.iocoder.yudao.module.farm.dal.mysql.specieslibrary.SpeciesLibraryMapper; import cn.iocoder.yudao.module.farm.enums.CommonConstants; +import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jakarta.annotation.Resource; @@ -48,14 +48,13 @@ public class BaseInfoServiceImpl implements BaseInfoService { @Resource private PlotInfoMapper plotInfoMapper; @Resource - private ProductionPlanMapper productionPlanMapper; - @Resource private SpeciesLibraryMapper speciesLibraryMapper; @Resource private PersonnelManagementMapper personnelManagementMapper; @Resource private GridInfoMapper gridInfoMapper; - + @Resource + private ProductionPlanService productionPlanService; @Override public String createBaseInfo(BaseInfoSaveReqVO createReqVO) { @@ -72,19 +71,30 @@ public class BaseInfoServiceImpl implements BaseInfoService { @Override public void updateBaseInfo(BaseInfoSaveReqVO updateReqVO) { + String baseId = updateReqVO.getId(); // 校验存在 - validateBaseInfoExists(updateReqVO.getId()); + validateBaseInfoExists(baseId); + BaseInfoDO sourceBaseInfoDO = baseInfoMapper.selectById(baseId); + BigDecimal oldArea = sourceBaseInfoDO.getArea(); + BigDecimal newArea = updateReqVO.getArea(); // 更新 BaseInfoDO updateObj = BeanUtils.toBean(updateReqVO, BaseInfoDO.class); baseInfoMapper.updateById(updateObj); + // 同步 + productionPlanService.syncBaseAreaToAllPlansByBaseId(baseId, newArea, oldArea); } @Override public void deleteBaseInfo(String id) { // 校验存在 validateBaseInfoExists(id); - // 删除 - baseInfoMapper.deleteById(id); + // 校验: 存在在种地块时 不允许删除 + boolean flag = productionPlanService.validateIncompletePlansBId("base_id",id); + if (flag) { + // 删除 + baseInfoMapper.deleteById(id); + } + } @Override @@ -184,39 +194,47 @@ public class BaseInfoServiceImpl implements BaseInfoService { } private void packageBaseInfo(long tenantId,List respVOS, Map employeeMap) { - for (BaseInfoRespVO obj : respVOS) { String baseId = obj.getId(); String baseName = obj.getName(); BigDecimal baseArea = obj.getArea(); List plotList = plotInfoMapper.selectList("base_id", baseId); - // 在种作物数量 - Integer cropCount = speciesLibraryMapper.getSpeciesCount(tenantId,baseId); - // 在种地块占比 - double plotRatio = 0.00; - // 在种地块数量 - int plotCount = 1; - // 地块总数 - int plotTotalCount = plotList.size(); - if (plotTotalCount > 0) { - plotRatio = Math.round((plotCount * 10000.0) / plotTotalCount) / 100.0; - } - - obj.setBaseOverview(new BaseInfoRespVO.BaseInfo(baseId,baseName,baseArea,cropCount,plotCount,plotTotalCount,plotRatio)); - + // 基地概述 + BaseInfoRespVO.BaseInfo baseOverview = this.packageBaseOverview(tenantId, baseId, baseName, baseArea, plotList); + obj.setBaseOverview(baseOverview); // 地块集合 - List targetList = new ArrayList<>(); - for (PlotInfoDO aDo : plotList) { - String plotManager = employeeMap.getOrDefault(aDo.getEmployeeId(), "系统"); - List gridInfos = this.packageGridInfo(aDo.getId()); - BaseInfoRespVO.PlotInfo target = new BaseInfoRespVO.PlotInfo(aDo.getId(), aDo.getPlotName(), aDo.getPlotColor(), aDo.getPlotArea(), plotManager,aDo.getPoint(),gridInfos); - targetList.add(target); - } + List targetList = this.packagePlotInfo(employeeMap, plotList); obj.setPlotOverviewList(targetList); } } + private BaseInfoRespVO.BaseInfo packageBaseOverview(long tenantId, String baseId, String baseName, BigDecimal baseArea, List plotList) { + // 在种作物数量 + Integer cropCount = speciesLibraryMapper.getSpeciesCount(tenantId, baseId); + // 在种地块占比 + double plotRatio = 0.00; + // 在种地块数量 + int plotCount = productionPlanService.getGrowingPlotCount(baseId); + // 地块总数 + int plotTotalCount = plotList.size(); + if (plotTotalCount > 0) { + plotRatio = Math.round((plotCount * 10000.0) / plotTotalCount) / 100.0; + } + return new BaseInfoRespVO.BaseInfo(baseId, baseName, baseArea, cropCount, plotCount, plotTotalCount, plotRatio); + } + + private List packagePlotInfo(Map employeeMap, List plotList) { + List targetList = new ArrayList<>(); + for (PlotInfoDO aDo : plotList) { + String plotManager = employeeMap.getOrDefault(aDo.getEmployeeId(), "系统"); + List gridInfos = this.packageGridInfo(aDo.getId()); + BaseInfoRespVO.PlotInfo target = new BaseInfoRespVO.PlotInfo(aDo.getId(), aDo.getPlotName(), aDo.getPlotColor(), aDo.getPlotArea(), plotManager, aDo.getPoint(), gridInfos); + targetList.add(target); + } + return targetList; + } + private List packageGridInfo(String plotId) { List gridList = gridInfoMapper.selectList("plot_id", plotId); if (ObjectUtils.isEmpty(gridList)) { diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/plotinfo/PlotInfoServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/plotinfo/PlotInfoServiceImpl.java index b2ba31d9..65cd6c74 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/plotinfo/PlotInfoServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/plotinfo/PlotInfoServiceImpl.java @@ -6,17 +6,23 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.module.farm.controller.admin.plotinfo.vo.PlotInfoPageReqVO; import cn.iocoder.yudao.module.farm.controller.admin.plotinfo.vo.PlotInfoSaveReqVO; +import cn.iocoder.yudao.module.farm.dal.dataobject.baseinfo.BaseInfoDO; import cn.iocoder.yudao.module.farm.dal.dataobject.plotinfo.PlotInfoDO; +import cn.iocoder.yudao.module.farm.dal.mysql.baseinfo.BaseInfoMapper; import cn.iocoder.yudao.module.farm.dal.mysql.plotinfo.PlotInfoMapper; +import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService; +import cn.iocoder.yudao.module.farm.utils.StrHelperUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; +import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PLOT_AREA_ERRORS; import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PLOT_INFO_NOT_EXISTS; /** @@ -28,15 +34,26 @@ import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PLOT_INFO_NO @Validated public class PlotInfoServiceImpl implements PlotInfoService { + @Resource + private BaseInfoMapper baseInfoMapper; @Resource private PlotInfoMapper plotInfoMapper; + @Resource + private ProductionPlanService productionPlanService; @Override public String createPlotInfo(PlotInfoSaveReqVO createReqVO) { LoginUser user = getLoginUser(); + // 验证地块面积总和 需要小于或等于 基地面积 + boolean flag = this.validateTotalPlotArea(createReqVO.getBaseId()); + if (flag) { + throw exception(PLOT_AREA_ERRORS); + } + // 插入 PlotInfoDO plotInfo = BeanUtils.toBean(createReqVO, PlotInfoDO.class); plotInfo.setId(IdUtil.fastUUID()); + plotInfo.setPlotId(StrHelperUtil.generate()); plotInfo.setTenantId(String.valueOf(user.getTenantId())); plotInfoMapper.insert(plotInfo); @@ -48,17 +65,31 @@ public class PlotInfoServiceImpl implements PlotInfoService { public void updatePlotInfo(PlotInfoSaveReqVO updateReqVO) { // 校验存在 validatePlotInfoExists(updateReqVO.getId()); +// PlotInfoDO sourcePlotInfoDO = plotInfoMapper.selectById(updateReqVO.getId()); +// String plotId = sourcePlotInfoDO.getPlotId(); +// BigDecimal oldArea = sourcePlotInfoDO.getPlotArea(); +// BigDecimal newArea = updateReqVO.getPlotArea(); + // 更新 PlotInfoDO updateObj = BeanUtils.toBean(updateReqVO, PlotInfoDO.class); plotInfoMapper.updateById(updateObj); + // 同步 +// productionPlanService.syncPlotAreaToAllPlansByBaseId(plotId,newArea,oldArea); } @Override public void deletePlotInfo(String id) { // 校验存在 - validatePlotInfoExists(id); + PlotInfoDO obj = plotInfoMapper.selectById(id); + if (obj == null) { + throw exception(PLOT_INFO_NOT_EXISTS); + } + // 校验: 存在在种地块时 不允许删除 + boolean flag = productionPlanService.validateIncompletePlansBId("plot_id",obj.getPlotId()); // 删除 - plotInfoMapper.deleteById(id); + if (flag) { + plotInfoMapper.deleteById(id); + } } @Override @@ -100,4 +131,25 @@ public class PlotInfoServiceImpl implements PlotInfoService { return plotInfoMapper.selectOne(queryWrapper); } + /** + * 验证: 地块总面积不得大于基地面积 + * @param baseId 基地面积 + */ + private boolean validateTotalPlotArea(String baseId){ + BaseInfoDO baseObj = baseInfoMapper.selectOne("id", baseId); + BigDecimal baseArea = baseObj.getArea(); + + List plotInfoDOS = plotInfoMapper.selectList("base_id", baseId); + if (plotInfoDOS == null || plotInfoDOS.isEmpty()) { + return true; + } + + BigDecimal plotTotalArea = plotInfoDOS.stream() + .map(PlotInfoDO::getPlotArea) + .filter(area -> area != null) // 重要:过滤null值 + .reduce(BigDecimal.ZERO, BigDecimal::add); + + return plotTotalArea.compareTo(baseArea) > 0 ; + } + } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanService.java index 6f06e0b0..54926520 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanService.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.farm.dal.dataobject.productionplan.ProductionPlan import cn.iocoder.yudao.framework.common.pojo.PageResult; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.List; /** @@ -74,4 +75,40 @@ public interface ProductionPlanService { */ List getBaseNameAndPlanList(); + /** + * 用于: 修改基地面积 + * 1. 基地面积不可以小于地块面积总和. + * 2. 基地面积不同步到每个关联生产计划中. + * + * @param baseId 基地编号 + * @param newArea 更新后的基地面积 + * @param oldArea 更新前的基地面积 + */ + void syncBaseAreaToAllPlansByBaseId(String baseId, BigDecimal newArea, BigDecimal oldArea); + + /** + * 用于: 修改地块面积 + * 1. 地块总面积不可大于基地面积 且 不可小于在种地块面积之和 + * 2. 基地面积不同步到每个关联生产计划中. + * + * @param plotId 地块编号 ,不是ID + * @param newArea 新地块面积 + * @param oldArea 旧地块面积 + */ + void syncPlotAreaToAllPlansByBaseId(String plotId, BigDecimal newArea, BigDecimal oldArea); + + /** + * 用于: 删除基地 + * 需要先验证改基地下属地块是否关联未完成的计划. 存在则不可删除. + * + * @param baseId 基地ID + */ + boolean validateIncompletePlansBId(String field, String baseId); + + /** + * 获取在种地块数量 + * @param baseId + * @return + */ + int getGrowingPlotCount(String baseId); } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanServiceImpl.java index 29751a80..83b66c9c 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/productionplan/ProductionPlanServiceImpl.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.farm.controller.admin.baseinfo.vo.BaseNamePlanRes import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanPageReqVO; import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; @@ -19,13 +20,13 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.module.farm.dal.mysql.productionplan.ProductionPlanMapper; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.math.BigDecimal; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; +import static cn.iocoder.yudao.module.farm.enums.CommonConstants.*; import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PRODUCTION_PLAN_NOT_EXISTS; /** @@ -156,4 +157,45 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { } + @Override + public void syncBaseAreaToAllPlansByBaseId(String baseId, BigDecimal newArea, BigDecimal oldArea) { + if (oldArea.compareTo(newArea) == 0) { + return ; + } + + List planList = productionPlanMapper.selectList("base_id", baseId); + planList.forEach(e -> e.setTotalArea(newArea.doubleValue())); + productionPlanMapper.updateBatch(planList); + } + + @Override + public void syncPlotAreaToAllPlansByBaseId(String plotId, BigDecimal newArea, BigDecimal oldArea) { +// if (oldArea.compareTo(newArea) == 0) { +// return ; +// } +// List planList = productionPlanMapper.selectList("plot_id", plotId); + + } + + @Override + public boolean validateIncompletePlansBId(String field,String baseId) { + List planList = productionPlanMapper.selectList(field, baseId); + Set planStatusSet = planList.stream() + .filter(e -> !ObjectUtils.notEqual(e.getPlanStatus(), PLAN_STATUS_3)) + .map(ProductionPlanDO::getPlanStatus) + .collect(Collectors.toSet()); + // 存在未完成状态的计划 不可删除 + if (planStatusSet.size() > 0) { + return false; + } + return false; + } + + @Override + public int getGrowingPlotCount(String baseId) { + List planList = productionPlanMapper.selectList("base_id", baseId); + long count = planList.stream().filter(e -> Objects.equals(e.getPlanStatus(), PLAN_STATUS_2)).count(); + return (int) count; + } + } \ No newline at end of file