feat (farm): 生产计划

- 修改调整按钮的业务逻辑 (计划状态变更)
- 修改重启按钮的业务逻辑
- 生产计划,计划状态定时任务
This commit is contained in:
达富斌
2025-08-30 10:54:44 +08:00
parent 7464c7af87
commit 02b67bd1ae
10 changed files with 160 additions and 60 deletions

View File

@@ -88,7 +88,8 @@ public class CropFarmingCenterController {
@PutMapping("/production-plan/restart") @PutMapping("/production-plan/restart")
public CommonResult<Boolean> restartPlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) { public CommonResult<Boolean> restartPlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) {
updateReqVO.setPlanStatus(CommonConstants.PLAN_STATUS_2); updateReqVO.setPlanStatus(CommonConstants.PLAN_STATUS_2);
cropFarmingCenterService.updateProductionPlan(updateReqVO); // TODO: 2025/8/29 这里存在业务逻辑问题 ,等产品确认
cropFarmingCenterService.restartProductionPlan(updateReqVO);
return success(true); return success(true);
} }
@Operation(summary = "生产计划-开始按钮") @Operation(summary = "生产计划-开始按钮")
@@ -107,6 +108,13 @@ public class CropFarmingCenterController {
return success(true); return success(true);
} }
@Operation(summary = "生产计划-调整按钮")
@PutMapping("/production-plan/revise")
public CommonResult<Boolean> revisePlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) {
cropFarmingCenterService.reviseProductionPlan(updateReqVO);
return success(true);
}
// 农事记录 // 农事记录
@GetMapping("/farming-record/page") @GetMapping("/farming-record/page")

View File

@@ -44,20 +44,25 @@ public class ProductionPlanRespVO {
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate harvestStartDate; private LocalDate harvestStartDate;
@Schema(description = "计划开始日期") // @Schema(description = "计划开始日期")
@JsonFormat(pattern = "yyyy-MM-dd") // @JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate plantingStartDate; // private LocalDate plantingStartDate;
//
@Schema(description = "计划结束日期") // @Schema(description = "计划结束日期")
@JsonFormat(pattern = "yyyy-MM-dd") // @JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate plantingEndDate; // private LocalDate plantingEndDate;
@Schema(description = "计划执行状态") @Schema(description = "计划执行状态")
private Integer planStatus; private Integer planStatus;
@Schema(description = "计划执行状态-名称") @Schema(description = "计划执行状态-名称")
private String planStatusName; private String planStatusName;
@Schema(description = "计划执行进度")
private Double planProgress; @Schema(description = "计划执行状态-子状态")
private Integer planSubStatus;
@Schema(description = "计划执行状态-子状态名称")
private String planSubStatusName;
@Schema(description = "逾期天数")
private Integer overdueDays;
@Schema(description = "租户ID") @Schema(description = "租户ID")

View File

@@ -34,15 +34,16 @@ public class ProductionPlanUpdateReqVO {
@Schema(description = "采收开始日期") @Schema(description = "采收开始日期")
private LocalDate harvestStartDate; private LocalDate harvestStartDate;
//
@Schema(description = "计划开始日期") // @Schema(description = "计划开始日期")
private LocalDate plantingStartDate; // private LocalDate plantingStartDate;
//
@Schema(description = "计划结束日期") // @Schema(description = "计划结束日期")
private LocalDate plantingEndDate; // private LocalDate plantingEndDate;
@Schema(description = "计划执行状态 (1:未开始;2:进行中;3:已完成;4:逾期)") @Schema(description = "计划执行状态 (1:未开始;2:进行中;3:已完成;4:逾期)")
private Integer planStatus; private Integer planStatus;
private Integer planSubStatus;
@Schema(description = "租户ID") @Schema(description = "租户ID")

View File

@@ -13,12 +13,6 @@ public class ProductionPlanSaveReqVO {
@Schema(description = "基础id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1050") @Schema(description = "基础id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1050")
private String id; private String id;
@Schema(description = "种植物种")
private String plantSpecies;
@Schema(description = "物种模型")
private String speciesModel;
@Schema(description = "排产开始日期") @Schema(description = "排产开始日期")
private LocalDate productionStartDate; private LocalDate productionStartDate;
@@ -28,9 +22,6 @@ public class ProductionPlanSaveReqVO {
@Schema(description = "采收开始日期") @Schema(description = "采收开始日期")
private LocalDate harvestStartDate; private LocalDate harvestStartDate;
@Schema(description = "种植区域ID", example = "10011")
private String cultivationAreaId;
@Schema(description = "基地id", example = "29734") @Schema(description = "基地id", example = "29734")
private String baseId; private String baseId;
@@ -44,4 +35,10 @@ public class ProductionPlanSaveReqVO {
private String plotName; private String plotName;
@Schema(description = "租户id") @Schema(description = "租户id")
private String tenantId; private String tenantId;
@Schema(description = "计划执行状态")
private Integer planStatus;
@Schema(description = "计划执行状态-子状态")
private Integer planSubStatus;
} }

View File

@@ -64,6 +64,7 @@ public class ProductionPlanDO extends BaseDO {
* 执行状态 * 执行状态
*/ */
private Integer planStatus; private Integer planStatus;
private Integer planSubStatus;
/** /**
* 种植日期 * 种植日期

View File

@@ -2,21 +2,23 @@ package cn.iocoder.yudao.module.farm.scheduled;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.farm.service.farmingrecord.FarmingRecordService; import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO;
import cn.iocoder.yudao.module.farm.dal.dataobject.productionplan.ProductionPlanDO;
import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService; import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.*;
/** /**
* @description: 生产计划 * @description: 生产计划状态
* 表关系 * 任务周期: 每天 00:00:00
* 模型管理: farm_model_management
* 模型管理-管理周期: farm_model_cycle
* 模型管理-管理周期-环境指标: farm_model_environment_index
* 模型管理-管理周期-病虫草害: farm_model_pest_disease_weed
* 模型管理-管理周期-气象灾害: farm_model_weather_disaster
* 模型管理-管理周期-农事事操: farm_model_farming_operation
* 模型管理-管理周期-农事操作-投入品: farm_model_farming_operation_input
* @author: binda * @author: binda
* @date: 2025/8/22 17:12 * @date: 2025/8/22 17:12
*/ */
@@ -26,17 +28,12 @@ import org.springframework.stereotype.Component;
public class ProductionPlanJob implements JobHandler { public class ProductionPlanJob implements JobHandler {
private final ProductionPlanService productionPlanService; private final ProductionPlanService productionPlanService;
private final FarmingRecordService farmingRecordService;
public ProductionPlanJob(ProductionPlanService productionPlanService, FarmingRecordService farmingRecordService) { public ProductionPlanJob(ProductionPlanService productionPlanService) {
this.productionPlanService = productionPlanService; this.productionPlanService = productionPlanService;
this.farmingRecordService = farmingRecordService;
} }
/** /**
* 1. 更新任务状态
* 2. 更新地块面积
* 3. 创建农事记录
* *
* @param param 参数 * @param param 参数
* @return * @return
@@ -44,23 +41,42 @@ public class ProductionPlanJob implements JobHandler {
*/ */
@Override @Override
public String execute(String param) throws Exception { public String execute(String param) throws Exception {
this.updatePlanStatusHandler(); this.updatePlanStatus();
this.updatePlanAreaHandler();
this.insertRecordHandler();
return "success"; return "success";
} }
private void updatePlanStatusHandler() { private void updatePlanStatus() {
// 当前日期
LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
List<ProductionPlanDO> plans = productionPlanService.getProductionPlans(null);
} List<ProductionPlanSaveReqVO> uList = new ArrayList<>();
for (ProductionPlanDO plan : plans) {
String id = plan.getId();
LocalDate productionStartDate = plan.getProductionStartDate();
LocalDate productionEndDate = plan.getProductionEndDate();
Integer planStatus = plan.getPlanStatus();
ProductionPlanSaveReqVO uDo = new ProductionPlanSaveReqVO();
uDo.setId(id);
private void updatePlanAreaHandler() { // 未完成 -> 逾期未开始
if (!ObjectUtils.notEqual(planStatus,PLAN_STATUS_1)) {
} if (today.isAfter(productionStartDate)) {
uDo.setPlanStatus(PLAN_STATUS_4);
private void insertRecordHandler() { uDo.setPlanSubStatus(PLAN_STATUS_5);
}
}
// 进行中 -> 逾期未结束
if (!ObjectUtils.notEqual(planStatus,PLAN_STATUS_2)) {
if (today.isAfter(productionEndDate)) {
uDo.setPlanStatus(PLAN_STATUS_4);
uDo.setPlanSubStatus(PLAN_STATUS_6);
}
}
uList.add(uDo);
}
productionPlanService.updateBatchProductionPlan(uList);
} }
} }

View File

@@ -31,4 +31,8 @@ public interface CropFarmingCenterService {
Double getTotalArea(Long tenantId); Double getTotalArea(Long tenantId);
void deleteProductionPlan(String id); void deleteProductionPlan(String id);
void reviseProductionPlan(ProductionPlanUpdateReqVO updateReqVO);
void restartProductionPlan(ProductionPlanUpdateReqVO updateReqVO);
} }

View File

@@ -24,9 +24,11 @@ import cn.iocoder.yudao.module.farm.service.plotinfo.PlotInfoService;
import cn.iocoder.yudao.module.farm.utils.StrHelperUtil; import cn.iocoder.yudao.module.farm.utils.StrHelperUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -34,7 +36,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.PLAN_MAP; import static cn.iocoder.yudao.module.farm.enums.CommonConstants.*;
import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PRODUCTION_PLAN_NOT_EXISTS; import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PRODUCTION_PLAN_NOT_EXISTS;
/** /**
@@ -82,6 +84,7 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
obj.setProductionEndDate(reqVO.getProductionEndDate()); obj.setProductionEndDate(reqVO.getProductionEndDate());
obj.setHarvestStartDate(reqVO.getHarvestStartDate()); obj.setHarvestStartDate(reqVO.getHarvestStartDate());
obj.setPlanStatus(CommonConstants.PLAN_STATUS_1); obj.setPlanStatus(CommonConstants.PLAN_STATUS_1);
obj.setPlanSubStatus(CommonConstants.PLAN_STATUS_1);
obj.setPlantingDate(e.getPlantingDate()); obj.setPlantingDate(e.getPlantingDate());
obj.setPlantingQuantity(e.getPlantingQuantity()); obj.setPlantingQuantity(e.getPlantingQuantity());
@@ -222,8 +225,8 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
PageResult<ProductionPlanDO> productionPlanDOPageResult = productionPlanMapper.selectPage2(reqVO); PageResult<ProductionPlanDO> productionPlanDOPageResult = productionPlanMapper.selectPage2(reqVO);
PageResult<ProductionPlanRespVO> resultData = BeanUtils.toBean(productionPlanDOPageResult, ProductionPlanRespVO.class); PageResult<ProductionPlanRespVO> resultData = BeanUtils.toBean(productionPlanDOPageResult, ProductionPlanRespVO.class);
resultData.getList().forEach(e -> { resultData.getList().forEach(e -> {
// todo 计划进度比例 // 逾期天数
e.setPlanProgress(0.00);
// 计划状态-名称 // 计划状态-名称
e.setPlanStatusName(PLAN_MAP.get(e.getPlanStatus())); e.setPlanStatusName(PLAN_MAP.get(e.getPlanStatus()));
// 模型 // 模型
@@ -278,4 +281,63 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
throw exception(PRODUCTION_PLAN_NOT_EXISTS); throw exception(PRODUCTION_PLAN_NOT_EXISTS);
} }
} }
@Override
public void reviseProductionPlan(ProductionPlanUpdateReqVO updateReqVO) {
this.changePlanStatus(updateReqVO);
productionPlanMapper.updateById(BeanUtils.toBean(updateReqVO, ProductionPlanDO.class));
}
private void changePlanStatus(ProductionPlanUpdateReqVO updateObj) {
String id = updateObj.getId();
ProductionPlanDO sourceObj = productionPlanMapper.selectOne("id", id);
// 当前状态
Integer currentPlanStatus = sourceObj.getPlanStatus();
// 当前子状态
Integer currentPlanSubStatus = sourceObj.getPlanSubStatus();
// 原始-排产结束日期
LocalDate originalProductionEndDate = sourceObj.getProductionEndDate();
// 最新-排产结束日期
LocalDate newProductionEndDate = updateObj.getProductionEndDate();
// 当前日期
LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
// 日期未修改
if (originalProductionEndDate.compareTo(newProductionEndDate) == 0) {
return;
}
// 只有逾期状态 才需要状态回退
if (ObjectUtils.notEqual(currentPlanStatus,PLAN_STATUS_4)) {
return;
}
// 状态回退 逾期未开始 -> 未开始
if (ObjectUtils.notEqual(currentPlanSubStatus,PLAN_STATUS_5)) {
if (today.isBefore(newProductionEndDate) || today.isEqual(newProductionEndDate)) { // eg: 8.1 - 8.21(today) - 8.30(newProductionEndDate)
updateObj.setPlanStatus(PLAN_STATUS_1);
updateObj.setPlanSubStatus(PLAN_STATUS_1);
}
if (today.isAfter(newProductionEndDate)) { // eg: 8.1 - 8.21(newProductionEndDate) - 8.30(today)
updateObj.setPlanStatus(PLAN_STATUS_4);
updateObj.setPlanSubStatus(PLAN_STATUS_5);
}
}
// 状态还原 逾期未结束 -> 进行中
if (ObjectUtils.notEqual(currentPlanSubStatus,PLAN_STATUS_6)) {
if (today.isBefore(newProductionEndDate) || today.isEqual(newProductionEndDate)) {
updateObj.setPlanStatus(PLAN_STATUS_2);
updateObj.setPlanSubStatus(PLAN_STATUS_2);
}
if (today.isAfter(newProductionEndDate)) {
updateObj.setPlanStatus(PLAN_STATUS_4);
updateObj.setPlanSubStatus(PLAN_STATUS_6);
}
}
}
@Override
public void restartProductionPlan(ProductionPlanUpdateReqVO updateReqVO) {
}
} }

View File

@@ -31,6 +31,7 @@ public interface ProductionPlanService {
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void updateProductionPlan(@Valid ProductionPlanSaveReqVO updateReqVO); void updateProductionPlan(@Valid ProductionPlanSaveReqVO updateReqVO);
void updateBatchProductionPlan(@Valid List<ProductionPlanSaveReqVO> updateReqVO);
/** /**
* 删除种植中心-生产计划-生产计划 * 删除种植中心-生产计划-生产计划

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.farm.service.productionplan;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.farm.controller.admin.baseinfo.vo.BaseNamePlanRespVO; import cn.iocoder.yudao.module.farm.controller.admin.baseinfo.vo.BaseNamePlanRespVO;
import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanPageReqVO; import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanPageReqVO;
import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO; import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO;
@@ -63,6 +64,11 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
productionPlanMapper.updateById(updateObj); productionPlanMapper.updateById(updateObj);
} }
@Override
public void updateBatchProductionPlan(List<ProductionPlanSaveReqVO> updateReqVO) {
productionPlanMapper.updateBatch(BeanUtils.toBean(updateReqVO,ProductionPlanDO.class));
}
@Override @Override
public void deleteProductionPlan(String id) { public void deleteProductionPlan(String id) {
// 校验存在 // 校验存在
@@ -90,7 +96,9 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
@Override @Override
public List<ProductionPlanDO> getProductionPlans(String plotId) { public List<ProductionPlanDO> getProductionPlans(String plotId) {
return null; LambdaQueryWrapperX<ProductionPlanDO> qw = new LambdaQueryWrapperX<>();
qw.eqIfPresent(ProductionPlanDO::getPlotId, plotId);
return productionPlanMapper.selectList(qw);
} }
@Override @Override
@@ -185,10 +193,7 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
.map(ProductionPlanDO::getPlanStatus) .map(ProductionPlanDO::getPlanStatus)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
// 存在未完成状态的计划 不可删除 // 存在未完成状态的计划 不可删除
if (planStatusSet.size() > 0) { return planStatusSet.size() <= 0;
return false;
}
return false;
} }
@Override @Override